python dict setdefault,混乱

2024-05-15 14:15:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我在找一个算法,我不明白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

Tags: in算法forfoodef事情whatdict
3条回答

d = dict()-->;初始化一个空字典并将其绑定到名称d;这样就有一个由名称d引用的字典对象({}

在外部for循环中 curr = d-->;将另一个名称curr绑定到同一对象。因此,名称(dcurr引用同一个对象)

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

curr = curr.setdefault(letter, {})

在上面的陈述中有两件事正在发生

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.".

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

B)将名称curr重新分配到上述返回值。现在,名称currd引用不同的对象。d是指对象{'f':{}},而curr是指空字典对象,实际上是d['f']的值。 这就是为什么在循环过程中,嵌套会发生在原始dictionary对象中。

阅读^{}的文档:它类似于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': {}}

setdefault(key[, default)

来自the docs

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.

用法示例

>>> 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, {})总是创建一个新的且空的dict,然后将其分配给curr。这意味着,不是重写值,而是为words中的每个元素在原始dict中添加嵌套级别。

我还认为,您希望用代码实现的是创建一个字典,将words中的每个元素都作为键,并将{}作为值,这样您就可以使用下面使用dict comprehension的代码来实现它:

def what(*words):
    return {word: {} for word in set(words)}

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

相关问题 更多 >