2017-01-23 83 views
1

我的意思並不是因爲標準這麼說,而是它的理由。規範說:爲什麼`dict_display`允許重複鍵?

如果給出了一個以逗號分隔的鍵/數據對序列,則會從左到右評估它們以定義詞典的條目:每個鍵對象都用作字典中的鍵存儲相應的數據。這意味着您可以在鍵/數據列表中多次指定相同的鍵,並且該鍵的最終字典值將是最後給出的值。

這意味着它是完全合法的形成dict通過:

d = { 'a': 1, 'b':2, 'b':3 } 

不過,我幾乎看不到,爲什麼一個想定義它的方式任何理由,最常見的我想這是一個錯誤。如果您將關鍵字參數與函數進行比較,則相應的結構將被禁止。

有沒有避免這種情況的好方法?

回答

3

此「bug」已被報告,討論並最終被拒絕 - 請參閱https://bugs.python.org/issue16385

由rejectors指定的主要理由是

代碼生成器可以依賴於能夠寫出重複鍵,而不必回去和擦除以前的輸出。

錯誤是出於兼容性的原因的問題。

2

我發現this discussion,這引起了這一點:

d = {spam(a): 'a', spam(b): 'BB', spam(c): 'Ccc'} 

這不僅凸顯,這必須是一個運行時的事情,但也有情況下,您可能要允許它。例如,當正在生成的代碼,或字典內涵,其覆蓋默認值等

defaults = {'a': 1, 'b': 2} 
specific = {'b': 3, 'c': 4} 
combined = {key: val for key, val in itertools.chain(defaults.items(), specific.items())} 

作爲我個人而言,它也與.update非常適合,它增加或更新的關鍵,而不是抱怨的時候它已經存在。

作爲一種方法來防止這種情況,當密鑰是有效的Python的關鍵字,你可以使用:

d = dict(a=1, b=2, b=3) 

你當然也可以讓自己的包裝,但它會很難看:

def uniqdict(items): 
    dct = {} 
    for key, val in items: 
     if key in dct: 
      raise KeyError('key {0:} already exists'.format(key)) 
     dct[key] = val 
    return dct 

uniqdict((('a', 1), ('b', 2), ('b', 3))) 
1

至少有幾種情況下,您可能會使用dict接受多個相同密鑰的行爲,因爲dictionary display is now evaluated left to right

1)如果多個鍵評估爲相同的輸出,但您只想採用最後一個實例。

例如,假設你想顯示一個數字,如果它是偶數或「奇數」;你可以使用字典:

def f(n): 
    return {True: n, n % 2: 'odd'}[True] 

當然,這個例子有更多可讀的方法,比如使用if-else子句,但它說明了這一點。

2)使用OrderedDict,利用此行爲是推薦的方法,可以在保留訂單的同時從列表中刪除重複項,如Raymond Hettinger says。例如:

from collections import OrderedDict 
list(OrderedDict.fromkeys(['a','b','d','d','a'])) 
# ['a', 'b', 'd'] 

如果您擔心的行爲,你應該簡單地檢查你的密鑰建立字典,例如assert len(keys) == len(set(keys))之前唯一的。你可以在添加它之前檢查關鍵字是否在字典中,if key not in my_dict: my_dict[key] = value