怀疑
我明白collections.defaultdict是这样分配的默认值的字典:怀疑
dict = collections.defaultdict(int) # default value of dict is 0
或
dict = collections.defaultdict(lambda: 5) # default value of dict is 5
然后我看到defaultdict的Python中像使用这个:
_dict = lambda : collections.defaultdict(_dict)
dict = _dict()
dict = dict["A"]
dict = dict["B"]
dict = dict["C"]
我很困惑的第一行:
_dict = lambda: collections.defaultdict(_dict)
什么是默认值?它似乎是一个无限的递归。
defaultdict()
需要工厂,并将呼叫工厂每次需要一个默认值的时间。如果您通过int
,每次需要新的默认值,则调用int()
。
您发现的代码使用lambda
作为工厂。每次你打电话时,它都会返回一个新的defaultdict(...)
对象。现在,defaultdict()
对象仍然需要一个工厂,在这种情况下,它只是重用相同的工厂对象。
这是可行的,因为名称_dict
仅在调用lambda时才被查找,并且只能在创建并调用名称_dict
时调用lambda;依赖关系周期起作用,因为只有在创建引用后才查找自引用。
这很像递归,但不是一回事。递归自动调用相同的函数,直到结束条件中断呼叫链。但在这里,没有自动呼叫链!当您需要新的默认值时,调用lambda
,并返回一个新的defaultdict(_dict)
对象。 就是这样。没有自动链,新铸造的defaultdict
有一个自己配置的工厂,但它不会自动调用。
该概念被称为autovivication。
当你说“新建的defaultdict有自己配置的工厂”时,是否意味着它会返回字典“{}”?默认值“{}”完全返回到哪里? – derek
@derek:不,它不会返回'{}'。它是另一个'defaultdict'对象,如果你试图访问一个不存在的键,它会调用工厂产生一个值。 –
@derek:那个工厂然后创建另一个'defaultdict'对象,它有一个工厂配置。等等。 –
也许你在某处忘了'lambda'?例如,请参阅[如何将defaultdicts的defaultdict [defaultdicts \]转换为dicts \ [dicts \]的词典?](// *.com/q/26496831),例如使用'递归'定义。这里的诀窍是'工厂'不会抬头,直到你*打电话给'工厂',在这个点上名称存在.. –
@MartijnPieters忘了添加lambda。查看我的更新 – derek
是的,它是递归的,但并不是无止境的。正如Martijn所说:“有一个诀窍,那就是只有在你打电话给'工厂'之前,'工厂'才会被抬起。 –