用defaultdict不理解这个lambda表达式

Z-J*_*ang 6 python lambda python-3.x defaultdict

我在pythontips看到了这个例子.当defaultdict接受参数"tree"并返回"tree"时,我不明白第二行.

import collections
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['color']['favor'] = "yellow"
# Works fine
Run Code Online (Sandbox Code Playgroud)

运行此代码后,我检查了some_dict的类型

defaultdict(< function < lambda > at 0x7f19ae634048 >, 
            {'color': defaultdict(
                  < function < lambda > at 0x7f19ae634048 >, {'favor': 'yellow'})})
Run Code Online (Sandbox Code Playgroud)

小智 6

这是创建递归的一种非常聪明的方法defaultdict。一开始理解起来有点棘手,但一旦你深入了解发生的事情,它实际上是递归的一个非常简单的使用。

在此示例中,我们定义了一个递归 lambda 函数 ,tree该函数返回 a ,defaultdict其构造函数为tree。为了清楚起见,让我们使用常规函数重写它。

from collections import defaultdict
from pprint import pprint

def get_recursive_dict():
    return defaultdict(get_recursive_dict)
Run Code Online (Sandbox Code Playgroud)

请注意,我们正在返回,defaultdict(get_recursive_dict)而不是defaultdict(get_recursive_dict())。我们想要传递defaultdict一个可调用对象(即函数get_recursive_dict)。实际上调用get_recursive_dict()会导致无限递归。

如果我们调用get_recursive_dict,我们会得到一个空值defaultdict,其默认值为该函数get_recursive_dict

recursive_dict = get_recursive_dict()
print(recursive_dict)
# defaultdict(<function get_recursive_dict at 0x0000000004FFC4A8>, {})
Run Code Online (Sandbox Code Playgroud)

让我们看看实际情况。创建 key 'alice',对应的 value 默认为空defaultdict,默认值为 function get_recursive_dict。请注意,这与我们的默认值相同recursive_dict

print(recursive_dict['alice'])
# defaultdict(<function get_recursive_dict at 0x0000000004AF46D8>, {})
print(recursive_dict)
# defaultdict(<function get_recursive_dict at 0x0000000004AF46D8>, {'alice': defaultdict(<function get_recursive_dict at 0x0000000004AF46D8>, {})})
Run Code Online (Sandbox Code Playgroud)

因此我们可以根据需要创建任意数量的嵌套字典。

recursive_dict['bob']['age'] = 2
recursive_dict['charlie']['food']['dessert'] = 'cake'
print(recursive_dict)
# defaultdict(<function get_recursive_dict at 0x00000000049BD4A8>, {'charlie': defaultdict(<function get_recursive_dict at 0x00000000049BD4A8>, {'food': defaultdict(<function get_recursive_dict at 0x00000000049BD4A8>, {'dessert': 'cake'})}), 'bob': defaultdict(<function get_recursive_dict at 0x00000000049BD4A8>, {'age': 2}), 'alice': defaultdict(<function get_recursive_dict at 0x00000000049BD4A8>, {})})
Run Code Online (Sandbox Code Playgroud)

一旦用键覆盖默认值,就无法再创建任意深度的嵌套字典。

recursive_dict['bob']['age']['year'] = 2016
# TypeError: 'int' object does not support item assignment
Run Code Online (Sandbox Code Playgroud)

我希望这能解决问题!