2013-03-21 107 views
3

python新手。我今天正在看一個算法,我不知道爲什麼dict d有值,curr沒有。對我來說,似乎沒有什麼正在做dict。python dict setdefault,困惑

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

回答

6

閱讀文檔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並設置我t值爲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': {}} 
+0

我得到的setdefault的一部分,我的代碼是你很大的不同。 – user584583 2013-03-21 18:51:30

+0

@ user584583我堅信,仔細閱讀文檔應該能夠解決您的問題,無論如何我已經添加了關於您的示例的解釋。 – Bakuriu 2013-03-21 19:01:25

2

d = dict() - >初始化一個空的字典,並將其綁定到名稱d ;所以你必須按名稱d

外裏面引用的字典對象({})for循環
curr = d - >結合另一名curr同一個對象。因此,名稱(dcurr指向同一個對象)

內側的內部for循環
在第一次迭代letter = 'f'

curr = curr.setdefault(letter, {}) 

有兩件事情是在上述聲明中發生的事情,

A)curr.setdefault(letter, {}) - >作爲每個文件:

「如果鍵在字典中,則返回其值。如果沒有,則插入具有默認值的鍵並返回默認值。默認默認爲None「。

由於,字母「F」不發生變異的初始目的是{'f':{}}初始字典對象,並返回值{},這不是初始字典對象,但是這是由於創建了一個新setdefault語句。此時,currd都引用了從突變後的初始字典對象。

B)的名稱curr上面提到的返回值的重新分配。現在,名稱currd指的是不同的對象。 d指對象{'f':{}},而curr是指一個空的字典對象,它實際上是d['f']值。 這就是爲什麼當我們通過循環時嵌套發生在原始字典對象中。