python新手。我今天看了一个算法,我无法弄清楚为什么dict d中有值,而curr没有。对我而言,似乎没有任何事情要做到dict d。
>>> 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
答案 0 :(得分:9)
阅读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
并将其设置为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': {}}
答案 1 :(得分:2)
d = dict()
- >初始化一个空字典并将其绑定到名称d
;所以你有一个名字{}
d
)
在外部for循环内
curr = d
- >将另一个名称curr
绑定到同一个对象。因此,名称(d
和curr
引用相同的对象)
内部for循环内部
在第一次迭代letter = 'f'
curr = curr.setdefault(letter, {})
上述陈述中有两件事情发生,
A)curr.setdefault(letter, {})
- >根据文件:
“如果密钥在字典中,则返回其值。如果不是,请插入值为default的密钥并返回默认值。默认默认为无。”。
因为字母'f'不在初始字典对象中,它将初始对象变为{'f':{}}
并返回值{}
,它不是初始字典对象,而是新字典对象由于setdefault语句而创建的。此时,curr
和d
都引用了从而变异为{'f':{}}
的初始字典对象。
B)将名称curr
重新分配给上述返回值。现在,名称curr
和d
引用不同的对象。 d
引用对象{'f':{}}
,而curr
引用空字典对象,实际上是d['f']
的值。
这就是为什么嵌套发生在原始字典对象中,因为我们经历了循环。
答案 2 :(得分:0)
setdefault(key[, default)
来自the docs:
如果
key
在字典中,请返回其值。如果不是,请插入值为key
的{{1}}并返回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
总是创建一个新的空字典,然后将其分配给curr = curr.setdefault(letter, {})
。这意味着您要覆盖curr
中的每个元素,而不是覆盖值,而是向原始字典添加嵌套级别。
我还认为,您要用代码实现的目标是创建一个字典,将words
中的每个元素作为键,并以words
作为值,因此您可以使用以下代码来实现使用 dict-comprehension :
{}
注意:,我已经添加了def what(*words):
return {word: {} for word in set(words)}
的说明,因为您的问题已特别针对此情况进行了查看,但我也想涵盖您的特定问题。