python dict setdefault,混乱

python dict setdefault,混乱,python,Python,我在寻找一种算法,但我不明白为什么dictd中有值,而curr中没有值。我认为似乎没有对dictd做任何事情 >>> def what(*words): ... d = {} ... print d ... for word in words: ... print 'word: ' + word ... curr = d ... for letter in word: ... curr =

我在寻找一种算法,但我不明白为什么dict
d
中有值,而
curr
中没有值。我认为似乎没有对dict
d
做任何事情

>>> def what(*words):
...     d = {}
...     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

阅读文档:它类似于
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
,并将其设置为
curr
,而
d
总是指原始的
dict
。正如您所看到的,在循环之后被修改,因为它的值是
{'f':{'o':{'o':{':'.}}}
,这与
{}
非常不同

您的困惑可能是因为
curr=curr.setdefault(字母,{})
总是创建一个新的空的
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': {}}
d=dict()
-->初始化一个空字典并将其绑定到名称
d
;因此您有一个由名称
d
引用的字典对象(
{}

外部for循环内部
curr=d
-->将另一个名称
curr
绑定到同一对象。因此,名称(
d
curr
指同一对象)

内部for循环内部
在第一次迭代中,字母='f'

curr = curr.setdefault(letter, {})
在上面的陈述中有两件事正在发生

A)
当前设置默认值(字母,{})
-->根据文档:

“如果键在字典中,则返回其值。如果不在字典中,则插入值为默认值的键并返回默认值。默认值默认为无。”

由于字母“f”不在初始字典对象中,因此它将初始对象变为
{f':{}}
,并返回值
{}
,该值不是初始字典对象,而是由于setdefault语句而创建的新对象。此时,
curr
d
都引用了最初的dictionary对象,该对象后来变为
{'f':{}

B) 将名称
curr
重新指定为上述返回值。现在,名称
curr
d
表示不同的对象
d
指的是对象
{'f':{}
,而
curr
指的是空字典对象,它实际上是
d['f']
的值。 这就是在循环中嵌套发生在原始dictionary对象中的原因

setdefault(键[,默认值)
发件人:

如果字典中有
key
,则返回其值。如果没有,则插入
key
,其值为
default
,并返回
default
default
默认值为
None

用法示例

>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> d.setdefault('a') # returns the corresponding value for key 'a'
1
>>> d.setdefault('a', 10) # returns the corresponding value for key 'a'
1
>>> d.setdefault('b') # returns the corresponding value for key 'b'
2
>>> d.setdefault('c', 100) # returns the corresponding value for key 'c'
3
>>> type(d.setdefault('z')) # because 'z' is not a key of d, None is returned which is the default value of default 
<class 'NoneType'>
>>> d.setdefault('z', 666) # returns 666 since key 'z' is not in d
666

注意:我已经添加了
setdefault
的解释,因为您的问题已经专门针对本案例进行了查看,但我也想涵盖您的具体问题。

我得到了setdefault部分,我的代码与您的代码大不相同。@user584583我坚信只要仔细阅读文档就可以了解决你的问题,无论如何,我已经添加了一个关于你的例子的解释。
def what(*words):
    return {word: {} for word in set(words)}