怀疑

2017-08-16 124 views
-1

我明白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) 

什么是默认值?它似乎是一个无限的递归。

+5

也许你在某处忘了'lambda'?例如,请参阅[如何将defaultdicts的defaultdict [defaultdicts \]转换为dicts \ [dicts \]的词典?](// stackoverflow.com/q/26496831),例如使用'递归'定义。这里的诀窍是'工厂'不会抬头,直到你*打电话给'工厂',在这个点上名称存在.. –

+0

@MartijnPieters忘了添加lambda。查看我的更新 – derek

+0

是的,它是递归的,但并不是无止境的。正如Martijn所说:“有一个诀窍,那就是只有在你打电话给'工厂'之前,'工厂'才会被抬起。 –

回答

0

defaultdict()需要工厂,并将呼叫工厂每次需要一个默认值的时间。如果您通过int,每次需要新的默认值,则调用int()

您发现的代码使用lambda作为工厂。每次你打电话时,它都会返回一个新的defaultdict(...)对象。现在,defaultdict()对象仍然需要一个工厂,在这种情况下,它只是重用相同的工厂对象

这是可行的,因为名称_dict仅在调用lambda时才被查找,并且只能在创建并调用名称_dict时调用lambda;依赖关系周期起作用,因为只有在创建引用后才查找自引用。

这很像递归,但不是一回事。递归自动调用相同的函数,直到结束条件中断呼叫链。但在这里,没有自动呼叫链!当您需要新的默认值时,调用lambda,并返回一个新的defaultdict(_dict)对象。 就是这样。没有自动链,新铸造的defaultdict有一个自己配置的工厂,但它不会自动调用。

该概念被称为autovivication

+0

当你说“新建的defaultdict有自己配置的工厂”时,是否意味着它会返回字典“{}”?默认值“{}”完全返回到哪里? – derek

+0

@derek:不,它不会返回'{}'。它是另一个'defaultdict'对象,如果你试图访问一个不存在的键,它会调用工厂产生一个值。 –

+0

@derek:那个工厂然后创建另一个'defaultdict'对象,它有一个工厂配置。等等。 –