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

时间:2017-08-20 01:11:50

标签: python python-3.x dictionary

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 让我们避免这个问题?第二种和第三种解决方案有何不同?

1 个答案:

答案 0 :(得分:2)

“每次创建一个新列表”表示每次调用setdefault(t, [])时,都会创建一个新的空list[]参数)作为默认值如果需要它。使用defaultdict可以避免这样做。

虽然两个解决方案都返回一个字典,但使用defaultdict的解决方案实际上返回的是defaultdict(list),它是内置dict类的子类。这通常不是问题。如果您print()返回的对象,最显着的效果可能是,因为两者的输出看起来完全不同。

如果由于某种原因不想要,可以将函数的最后一个语句更改为:

    return dict(d)

将创建的defaultdict(list)转换为常规dict