[英]python dict setdefault, confused
I was looking for an algorithm, and I can't figure out why the dict d
has values in it and curr
does not. 我正在寻找一种算法,我无法弄清楚为什么dict d
有值,而curr
没有。 I think it does not seem like anything is being done to dict d
. 我认为似乎没有任何事情要做到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
Read the documentation for dict.setdefault
: it is like get
but if the key wasn't present then it is also set: 阅读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'}
Modifying a little your example: 修改一下你的例子:
>>> 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': {'.': '.'}}}}
As you can see curr
changes, because when calling setdefault
it sometimes(in your example always) create a new dict
and set it as value to curr
, while d
always refers to the original dict
. 正如您可以看到curr
更改,因为在调用setdefault
它有时(在您的示例中始终)创建一个新的dict
并将其设置为curr
值,而d
始终引用原始的dict
。 As you can see it is modified after the loop, since it's value is {'f': {'o': {'o': {'.': '.'}}}}
which is quite different from {}
. 你可以看到它在循环之后被修改,因为它的值是{'f': {'o': {'o': {'.': '.'}}}}
这与{}
完全不同。
Probably your confusion is due to the fact that curr = curr.setdefault(letter, {})
always create a new and empty dict
, which is then assigned to curr
(and thus for every letter you add a nesting level to the original dict
instead of overwriting the values). 可能你的困惑是由于curr = curr.setdefault(letter, {})
总是创建一个新的 空 dict
,然后将其分配给curr
(因此对于每个字母,你都会为原始dict
添加嵌套级别而不是覆盖价值观)。
See this: 看到这个:
>>> 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': {}}}}
As you can see for every level the my_dict
has a new nesting level. 正如您可以在每个级别看到的那样, my_dict
具有新的嵌套级别。
Maybe, but I'm just guessing, you wanted to obtain something like 'foo' -> {'f': {}, 'o': {}}
, in which case you should do: 也许,但我只是在猜测,你想获得类似'foo' -> {'f': {}, 'o': {}}
,在这种情况下你应该这样做:
>>> my_dict = {}
>>> for letter in 'foo':
... my_dict.setdefault(letter, {})
...
>>> my_dict
{'o': {}, 'f': {}}
d = dict()
--> initializes an empty dictionary and binds it to the name d
; d = dict()
- >初始化一个空字典并将其绑定到名称d
; so you have a dictionary object ( {}
) referenced by name d
所以你有一个名字d
引用的字典对象( {}
)
Inside the outer for loop 在外部for循环内
curr = d
--> binds another name curr
to the same object. curr = d
- >将另一个名称curr
绑定到同一个对象。 So, names ( d
and curr
refer to the same object) 所以,名字( d
和curr
指的是同一个对象)
Inside the inner for loop 在内部for循环内
During the first iteration letter = 'f'
在第一次迭代期间, letter = 'f'
curr = curr.setdefault(letter, {})
There are 2 things that are happening in the above statement, 上述声明中有两件事情发生,
A) curr.setdefault(letter, {})
--> As per documentation: A) curr.setdefault(letter, {})
- >根据文档:
"If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.". “如果key在字典中,则返回其值。如果不是,请插入值为default并返回默认值。默认默认为None。”。
Since, the letter 'f' is not in the initial dictionary object it mutates the initial object to {'f':{}}
and returns the value {}
, which is not the initial dictionary object, but a new one that was created because of the setdefault statement. 因为,字母'f'不在初始字典对象中,它将初始对象变为{'f':{}}
并返回值{}
,它不是初始字典对象,而是创建的新字典对象因为setdefault语句。 At this time both curr
and d
refer to the initial dictionary object which has since mutated to {'f':{}}
. 此时curr
和d
引用了初始字典对象,后者已经变为{'f':{}}
。
B) Reassignment of the name curr
to the return value mentioned above. B)将名称curr
重新分配给上面提到的返回值。 Now, the names curr
and d
refer to different objects. 现在,名称curr
和d
引用不同的对象。 d
refers to the object {'f':{}}
, while curr
refers to an empty dictionary object, which is actually the value of d['f']
. d
引用对象{'f':{}}
,而curr
引用空字典对象,实际上是d['f']
。 This is why the nesting happens in the original dictionary object, as we go through the loop. 这就是为什么嵌套发生在原始字典对象中,因为我们经历了循环。
setdefault(key[, default)
If
key
is in the dictionary, return its value. 如果key
在字典中,则返回其值。 If not, insertkey
with a value ofdefault
and returndefault
. 如果没有,插入key
,值为default
和返回default
。default
defaults toNone
.default
默认为None
。
Usage examples 用法示例
>>> 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
I think you are confused because curr = curr.setdefault(letter, {})
always creates a new and empty dict , which is then assigned to curr
. 我觉得你很困惑,因为curr = curr.setdefault(letter, {})
总是会创建一个新的空字典 ,然后将其分配给curr
。 This means that instead of overwriting the values, you are adding a nesting level to the original dict for every element in words
. 这意味着您不是覆盖值,而是为words
每个元素添加嵌套级别到原始字典。
I also think that what you want to achieve with your code is to create a dictionary with every element in words
as key with {}
as value, so you can achieve it using the following code that uses a dict-comprehension : 我还认为,要实现你的代码是什么创造一个字典,在每一个元素words
与键{}
作为值,所以你可以使用一个使用字典,理解下面的代码实现它:
def what(*words):
return {word: {} for word in set(words)}
Note: I have added the explanation of setdefault
since your questions has been viewed particularly for this case, but I wanted to cover your specific question too. 注意:我已经添加了setdefault
的解释,因为您的问题特别针对此案例进行了查看,但我也想介绍您的具体问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.