python dict setdefault,困惑

问题描述:

python新手。我今天正在看一个算法,我不知道为什么dict d有值,curr没有。对我来说,似乎没有什么正在做dict。python dict setdefault,困惑

>>> def what(*words): 
...  d = dict() 
...  print d 
...  for word in words: 
...  print 'word: ' + word 
...   curr = d 
...   for letter in word: 
...    curr = curr.setdefault(letter, {}) 
...   curr = curr.setdefault('.', '.') 
...  print d 
...  print '?' 
...  print curr 
...  return 1 
... 
>>> what('foo') 
{} 
word: foo 
{'f': {'o': {'o': {'.': '.'}}}} 
? 
. 
1 

阅读文档dict.setdefault:它像get但如果键不存在,那么它也被设置:

>>> my_dict = {} 
>>> my_dict.setdefault('some key', 'a value') 
'a value' 
>>> my_dict 
{'some key': 'a value'} 
>>> my_dict.get('some key2', 'a value2') 
'a value2' 
>>> my_dict 
{'some key': 'a value'} 

修改一点点你的例子:

>>> def what(*words): 
...  d = dict() 
...  for word in words: 
...    curr = d 
...    for letter in word: 
...      curr = curr.setdefault(letter, {}) 
...    curr = curr.setdefault('.', '.') 
...    print 'curr is now: %r while d is %r' % (curr, d) 
... 
>>> what('foo') 
curr is now: '.' while d is {'f': {'o': {'o': {'.': '.'}}}} 

正如你所看到的curr的变化,因为当调用setdefault它有时(在你的例子总是)创建一个新的dict并设置我t值为curr,而d总是指原来的dict。正如你可以看到它后循环修改,因为它的值是{'f': {'o': {'o': {'.': '.'}}}}这是从{}完全不同。

也许你的困惑是由于这样的事实:curr = curr.setdefault(letter, {})总是创建dict,然后将其分配给curr(从而为每一个字母添加一个嵌套级别到原来dict代替覆盖值)。

看到这个:

>>> my_dict = {} 
>>> curr = my_dict 
>>> for letter in 'foo': 
...  print 'my_dict is now %r. curr is now %r' % (my_dict, curr) 
...  curr = curr.setdefault(letter, {}) 
... 
my_dict is now {}. curr is now {} 
my_dict is now {'f': {}}. curr is now {} 
my_dict is now {'f': {'o': {}}}. curr is now {} 
>>> my_dict 
{'f': {'o': {'o': {}}}} 

正如你可以看到每一级my_dict有一个新的嵌套级别。

也许吧,但我只是猜测,你想获得类似'foo' -> {'f': {}, 'o': {}},在这种情况下,你应该做的:

>>> my_dict = {} 
>>> for letter in 'foo': 
...  my_dict.setdefault(letter, {}) 
... 
>>> my_dict 
{'o': {}, 'f': {}} 
+0

我得到的setdefault的一部分,我的代码是你很大的不同。 – user584583 2013-03-21 18:51:30

+0

@ user584583我坚信,仔细阅读文档应该能够解决您的问题,无论如何我已经添加了关于您的示例的解释。 – Bakuriu 2013-03-21 19:01:25

d = dict() - >初始化一个空的字典,并将其绑定到名称d ;所以你必须按名称d

外里面引用的字典对象({})for循环
curr = d - >结合另一名curr同一个对象。因此,名称(dcurr指向同一个对象)

内侧的内部for循环
在第一次迭代letter = 'f'

curr = curr.setdefault(letter, {}) 

有两件事情是在上述声明中发生的事情,

A)curr.setdefault(letter, {}) - >作为每个文件:

“如果键在字典中,则返回其值。如果没有,则插入具有默认值的键并返回默认值。默认默认为None“。

由于,字母“F”不发生变异的初始目的是{'f':{}}初始字典对象,并返回值{},这不是初始字典对象,但是这是由于创建了一个新setdefault语句。此时,currd都引用了从突变后的初始字典对象。

B)的名称curr上面提到的返回值的重新分配。现在,名称currd指的是不同的对象。 d指对象{'f':{}},而curr是指一个空的字典对象,它实际上是d['f']值。 这就是为什么当我们通过循环时嵌套发生在原始字典对象中。