在Think Python中,作者介绍了defaultdict。以下是关于defaultdict的书的节选:
If you are making a dictionary of lists, you can often write simpler code using defaultdict. In my solution to Exercise 12-2, which you can get from http://thinkpython2.com/code/anagram_sets.py, I make a dictionary that maps from a sorted string of letters to the list of words that can be spelled with those letters. For example, 'opst' maps to the list ['opts', 'post', 'pots', 'spot', 'stop', 'tops']. Here’s the original code:
def all_anagrams(filename): d = {} for line in open(filename): word = line.strip().lower() t = signature(word) if t not in d: d[t] = [word] else: d[t].append(word) return d
This can be simplified using setdefault, which you might have used in Exercise 11-2:
def all_anagrams(filename): d = {} for line in open(filename): word = line.strip().lower() t = signature(word) d.setdefault(t, []).append(word) return d
This solution has the drawback that it makes a new list every time, regardless of whether it is needed. For lists, that’s no big deal, but if the factory function is complicated, it might be. We can avoid this problem and simplify the code using a defaultdict:
def all_anagrams(filename): d = defaultdict(list) for line in open(filename): word = line.strip().lower() t = signature(word) d[t].append(word) return d
以下是signature
函数的定义:
def signature(s):
"""Returns the signature of this string.
Signature is a string that contains all of the letters in order.
s: string
"""
# TODO: rewrite using sorted()
t = list(s)
t.sort()
t = ''.join(t)
return t
关于第二个解决方案,我的理解是setdefault
检查t
(单词的签名)是否作为键存在,如果不是,它将其设置为键并将空列表设置为其值,然后append
将该词附加到它的后面。如果t
存在,setdefault
返回其值(至少包含一个项的列表,它是一个表示单词的字符串),并且append
将该单词追加到此列表。在
关于第三个解决方案,我所理解的是d
,它表示一个defaultdict,它使t
成为一个键,并将一个空列表设置为其值(如果t
还没有作为键存在),那么这个词就被追加到列表中。如果t
已经存在,则返回其值(列表),并将单词附加到该值。在
第二个和第三个解决方案有什么区别?第二个解决方案中的代码每次都会生成一个新列表,而不管是否需要它?setdefault
是如何对此负责的?使用defaultdict如何避免这个问题?第二种和第三种解决方案有何不同?在
“makea new list every time”意味着每次调用
setdefault(t, [])
,就会创建一个新的空list
(参数[]
)作为默认值,以防需要它。使用defaultdict
可以避免这样做。在尽管两个解决方案都返回一个字典,但使用
defaultdict
的解决方案实际上返回了一个defaultdict(list)
,它是内置dict
类的子类。这通常不是问题。最显著的效果可能是print()
返回的对象,因为这两个对象的输出看起来非常不同。在如果出于任何原因不希望这样做,可以将函数的最后一条语句更改为:
将创建的
defaultdict(list)
转换为常规的dict
。在相关问题 更多 >
编程相关推荐