Python 使用defaultdict的解决方案与使用setdefault的解决方案有什么区别?
在ThinkPython中,作者介绍了defaultdict。以下是本书中有关defaultdict的摘录:Python 使用defaultdict的解决方案与使用setdefault的解决方案有什么区别?,python,python-3.x,dictionary,Python,Python 3.x,Dictionary,在ThinkPython中,作者介绍了defaultdict。以下是本书中有关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 如果你正在
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
如果你正在编一本列表词典,你通常可以写得更简单一些
使用defaultdict编写代码。在我对练习12-2的解答中,你可以
从,我做一个
从已排序的字母字符串映射到字母列表的字典
可以用这些字母拼写的单词。例如,“opst”映射
到列表['opts','post','pots','spot','stop','top']。这是
原代码:
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中使用setdefault:
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
以下是签名
函数的定义:
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
将单词追加到此列表中
我对第三种解决方案的理解是,表示defaultdict的d
,将t
设置为一个键,并将空列表设置为其值(如果t
尚未作为键存在),然后将该词附加到列表中。如果t
已经存在,则返回其值(列表),并将单词附加到该值
第二种和第三种解决方案之间的区别是什么?我知道第二个解决方案中的代码每次都会生成一个新列表,而不管是否需要它,这意味着什么?setdefault
如何对此负责?使用defaultdict如何避免这个问题?第二种和第三种解决方案有何不同?每次创建一个新列表”意味着每次调用setdefault(t,[])
时,都会创建一个新的空列表([]
参数)作为默认值,以备需要。使用defaultdict
可以避免这样做
尽管这两种解决方案都返回一个字典,但使用defaultdict
的解决方案实际上返回了一个defaultdict(list)
,它是内置dict
类的子类。这通常不是问题。最显著的影响可能是如果您print()
返回的对象,因为这两个对象的输出看起来完全不同
如果出于任何原因不希望这样做,可以将函数的最后一条语句更改为:
return dict(d)
要将创建的defaultdict(list)
转换为常规dict
谢谢!因此,为了确保正确,当调用setdefault(t,[])
时,首先计算[]
,然后setdefault
检查t
是否存在?@MahmudMuhammadNaguib yes,这是python语义所要求的。列表文字告诉解释器“创建此列表”@juanpa.arrivillaga谢谢!如果.setdefault()支持第二个参数(默认值)是可调用的或类型,而不是实例或其他值的情况下的延迟计算,那就太好了。但现在这可能不是一个现实的改变(…将这种缺乏快捷方式评估的情况视为“不是bug”(我同意这一结论)。但我找不到任何关于懒惰评估的内容。