9

我一直在寻找一种算法,但我无法弄清楚为什么 dictd中有值而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
4

3 回答 3

13

阅读文档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, {}) 总是创建一个newempty 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': {}}
于 2013-03-21T18:49:08.203 回答
4

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

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

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

curr = curr.setdefault(letter, {})

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

A) curr.setdefault(letter, {})--> 根据文档:

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

因为字母 'f' 不在初始字典对象中,它会将初始对象突变为{'f':{}}并返回 value {},它不是初始字典对象,而是由于 setdefault 语句而创建的新对象。此时两者curr和都d引用了初始字典对象,该对象已突变为{'f':{}}.

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

于 2014-08-12T11:38:28.823 回答
0

setdefault(key[, default)

文档

如果key在字典中,则返回其值。如果不是,则插入keydefault并返回defaultdefault默认为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.

我还认为您希望使用代码实现的目标是创建一个字典,其中每个元素都words作为键和{}值,因此您可以使用以下使用dict-comprehension的代码来实现它:

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

注意:我已经添加了解释,setdefault因为您的问题已经特别针对这种情况进行了查看,但我也想涵盖您的具体问题。

于 2019-07-12T03:56:47.897 回答