Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用defaultdict的解决方案与使用setdefault的解决方案有什么区别?_Python_Python 3.x_Dictionary - Fatal编程技术网

Python 使用defaultdict的解决方案与使用setdefault的解决方案有什么区别?

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 如果你正在

在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
如果你正在编一本列表词典,你通常可以写得更简单一些 使用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”(我同意这一结论)。但我找不到任何关于懒惰评估的内容。