Python defaultdict 和 lambda
Posted
技术标签:
【中文标题】Python defaultdict 和 lambda【英文标题】:Python defaultdict and lambda 【发布时间】:2012-01-15 04:55:53 【问题描述】:在别人的代码中,我读到了以下两行:
x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))
由于 defaultdict 的参数是一个默认工厂,我认为第一行的意思是当我为一个不存在的键 k 调用 x[k] 时(例如像 v=x[k] 这样的语句),键值pair (k,0) 将被自动添加到字典中,就像首先执行语句 x[k]=0 一样。我说的对吗?
你呢?似乎默认工厂将创建一个默认为 0 的 defaultdict。但这具体意味着什么?我尝试在 Python shell 中使用它,但无法弄清楚它到底是什么。
【问题讨论】:
【参考方案1】:我认为第一行的意思是当我为一个不存在的键
k
(比如v=x[k]
这样的语句)调用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
而言。
【讨论】:
另一种在不使用 lambda 的情况下创建像y
这样的 deafultdict 的方法是使用来自 functools
的 partial
,如下所示:y = defaultdict(partial(defaultdict, int))
快速跟进:为什么defaultdict(int)
的工作方式与lambda: 0
的工作方式相同?或者换句话说,为什么defaultdict(int)
总是返回 0 作为值?
@briandk:因为int()
返回零。【参考方案2】:
您对第一个所做的事情是正确的。至于y
,当y
中不存在某个键时,它会创建一个默认为0 的defaultdict,因此您可以将其视为嵌套字典。考虑以下示例:
y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2'] # 0
print dict(y['k1']) # 'k2': 0
要在没有 defaultdict 的情况下创建等效的嵌套字典结构,您需要为 y['k1']
创建一个内部 dict,然后将 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
【讨论】:
【参考方案3】:defaultdict
对其构造函数采用可调用的零参数,正如您正确解释的那样,当找不到密钥时调用该构造函数。
lambda: 0
当然总是返回零,但首选的方法是 defaultdict(int)
,它会做同样的事情。
至于第二部分,作者想创建一个新的defaultdict(int)
,或嵌套字典,只要在***字典中找不到键。
【讨论】:
@mjb - int 在这种情况下是首选,因为它更具可读性。使用 int 可能也快一点,但主要原因还是它的代码更清晰。 Via docs.python.org:“总是返回零的函数 int() 只是常量函数的一个特例。创建常量函数的更快、更灵活的方法是使用 itertools.repeat () 可以提供任何常数值(不仅仅是零)”。然后显示了一个 itertools.repeat() 示例,这非常好。我推荐阅读:docs.python.org/2/library/collections.html#defaultdict-objects【参考方案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
【讨论】:
【参考方案5】:y = defaultdict(lambda:defaultdict(lambda:0))
如果你试试这个y['a']['b'] += 1
会很有帮助
【讨论】:
以上是关于Python defaultdict 和 lambda的主要内容,如果未能解决你的问题,请参考以下文章
Python collections.defaultdict() 与 dict的使用和区别