Python defaultdict和lambda


71

在其他人的代码中,我阅读了以下两行:

x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))

由于defaultdict的参数是默认工厂,因此我认为第一行表示当我为不存在的键k调用x [k](例如类似v = x [k]的语句)时,键值对(k ,0)会自动添加到字典中,就像首先执行语句x [k] = 0一样。我对么?

那y呢?似乎默认工厂将创建一个默认值为0的defaultdict。但这具体意味着什么?我试图在Python shell中尝试使用它,但无法弄清楚它到底是什么。

Answers:


65

我认为第一行意味着当我要求x[k]一个不存在的键k(例如类似的语句v=x[k])时,键值对(k,0)将被自动添加到字典中,就像该语句x[k]=0首先执行一样。

那就对了。这是习惯用语

x = defaultdict(int)

对于y,当您执行时y["ham"]["spam"],如果密钥不存在"ham"y则将其插入。与之关联的值将变成一个defaultdict,其中"spam"将自动插入一个带有的值0

即,y是一种“两层” defaultdict。如果为"ham" not in y,则评估y["ham"]["spam"]就像在做

y["ham"] = {}
y["ham"]["spam"] = 0

就普通而言dict


5
y不使用lambda一样创建deafultdict的另一种方法是使用partialfrom functools,例如:y = defaultdict(partial(defaultdict, int))
Lauritz V. Thaulow 2011年

1
快速跟进:为什么defaultdict(int)工作方式lambda: 0与之相同?或者换句话说,为什么defaultdict(int)总会返回0?
briandk

3
@briandk:因为int()返回零。
弗雷德·富

10

你对第一个是正确的。至于y,当键中不存在键时,它将创建一个默认值为0的defaultdict y,因此您可以将其视为嵌套字典。考虑以下示例:

y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2']   # 0
print dict(y['k1'])   # {'k2': 0}

要创建一个没有defaultdict的等效嵌套字典结构,您需要为其创建一个内部dict y['k1'],然后将其设置y['k1']['k2']为0,但是当defaultdict遇到未曾看到的键时,它将在幕后进行所有操作:

y = {}
y['k1'] = {}
y['k1']['k2'] = 0

以下功能可能有助于在解释器上进行操作,以加深您的理解:

def to_dict(d):
    if isinstance(d, defaultdict):
        return dict((k, to_dict(v)) for k, v in d.items())
    return d

这将返回等同于嵌套defaultdict的dict,它更易于阅读,例如:

>>> y = defaultdict(lambda: defaultdict(lambda: 0))
>>> y['a']['b'] = 5
>>> y
defaultdict(<function <lambda> at 0xb7ea93e4>, {'a': defaultdict(<function <lambda> at 0xb7ea9374>, {'b': 5})})
>>> to_dict(y)
{'a': {'b': 5}}

7

defaultdict 如您正确解释的那样,采用可调用其构造函数的零参数,当找不到键时调用该参数。

lambda: 0当然会总是返回零,但是首选的方法是defaultdict(int),它会做同样的事情。

至于第二部分,defaultdict(int)只要在顶级词典中找不到键,作者就想创建一个new或嵌套词典。


4
@mjb-在这种情况下,首选int,因为它更具可读性。使用int可能也要快一些,但是再次主要原因是它的代码更清晰。
三联画

3
通过docs.python.org:“始终返回零的函数int()只是常量函数的一种特殊情况。创建常量函数的更快,更灵活的方法是使用itertools.repeat(),它可以提供任何常量值(不只是零)”。然后显示一个itertools.repeat()示例,这非常不错。我建议阅读:docs.python.org/2/library/collections.html#defaultdict-objects
Dmitry

4

所有答案都足够好了,我还是给出了添加更多信息的答案:

“ defaultdict需要一个可调用的参数。该可调用对象的返回结果是当您尝试使用不存在的键访问字典时字典返回的默认值。”

这是一个例子

SAMPLE= {'Age':28, 'Salary':2000}
SAMPLE = defaultdict(lambda:0,SAMPLE)

>>> SAMPLE
defaultdict(<function <lambda> at 0x0000000002BF7C88>, {'Salary': 2000, 'Age': 28})

>>> SAMPLE['Age']----> This will return 28
>>> SAMPLE['Phone']----> This will return 0   # you got 0 as output for a non existing key inside SAMPLE

1

y = defaultdict(lambda:defaultdict(lambda:0))

如果您尝试这样做会有所帮助 y['a']['b'] += 1

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.