在 Think Python 中,作者介绍了 defaultdict 。以下是本书关于 defaultdict 的摘录:
如果要制作列表字典,通常可以更简单地编写 使用defaultdict的代码。在我的练习12-2的解决方案中,你可以 从http://thinkpython2.com/code/anagram_sets.py得到,我做了一个 从排序的字母串映射到列表的字典 可以用这些字母拼写的单词。例如,'opst'地图 到列表['opts','post','pots','spot','stop','tops']。这里的 原始代码:
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
这可以使用setdefault进行简化,您可能已经在练习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
此解决方案的缺点是,无论是否需要,它每次都会生成一个新列表。对于列表来说,这没什么大不了的,但如果工厂功能很复杂,那可能就是这样。我们可以避免这个问题并简化 使用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
成为一个键并将空列表设置为其值(如果{{ 1}}不存在作为键),然后该单词被附加到列表中。如果t
已经存在,则返回其值(列表),并附加该单词。
第二种和第三种解决方案有什么区别? I这意味着第二个解决方案中的代码每次都会生成一个新列表,无论是否需要它? t
如何对此负责?如何使用 defaultdict 让我们避免这个问题?第二种和第三种解决方案有何不同?
答案 0 :(得分:2)
“每次创建一个新列表”表示每次调用setdefault(t, [])
时,都会创建一个新的空list
([]
参数)作为默认值如果需要它。使用defaultdict
可以避免这样做。
虽然两个解决方案都返回一个字典,但使用defaultdict
的解决方案实际上返回的是defaultdict(list)
,它是内置dict
类的子类。这通常不是问题。如果您print()
返回的对象,最显着的效果可能是,因为两者的输出看起来完全不同。
如果由于某种原因不想要,可以将函数的最后一个语句更改为:
return dict(d)
将创建的defaultdict(list)
转换为常规dict
。