2016-09-13 71 views
4

我們可以通過使用多重繼承平凡創建OrderedCounterOrderedDict爲什麼不使用超級?

>>> from collections import Counter, OrderedDict 
>>> class OrderedCounter(Counter, OrderedDict): 
...  pass 
... 
>>> OrderedCounter('Mississippi').items() 
[('M', 1), ('i', 4), ('s', 4), ('p', 2)] 

糾正我,如果我錯了,但這個關鍵依賴於以下事實:Counter uses super

class Counter(dict): 
    def __init__(*args, **kwds): 
     ... 
     super(Counter, self).__init__() 
     ... 

也就是說,魔術技巧的作品,因爲

>>> OrderedCounter.__mro__ 
(__main__.OrderedCounter, 
collections.Counter, 
collections.OrderedDict, 
dict, 
object) 

super調用必須根據'兄弟姐妹befo父母的規則mro,自定義班級使用OrderedDict作爲存儲後端。

但是一個同事最近指出,出乎我的意料,那OrderedDictdoesn't使用超:

def __setitem__(self, key, value, 
       dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link): 
    ... 
    # <some weird stuff to maintain the ordering here> 
    dict_setitem(self, key, value) 

起初我以爲這可能是因爲OrderedDict是先和雷蒙德沒有理會後來去改變它,但似乎super早於OrderedDict

爲什麼OrderedDict顯式調用dict.__setitem__

爲什麼它需要成爲一個kwarg?這在鑽石繼承情況下使用OrderedDict時不會造成麻煩,因爲它直接傳遞給父類,而不是委託給mro中的下一行?

回答

0

這是一種微觀優化。查詢dict_setitem的說法比查找dict.__setitem__super().__setitem__稍快。

如果您有另一個類重寫__setitem__,但是OrderedDict不是爲那種鑽石結構方法重寫而設計的,則可能會導致多繼承問題。爲了支持OrderedDict,如果他們嘗試索引OrderedDict而排序信息與字典結構不一致,則必須非常小心地保證另一個類的方法可能會看到什麼。這樣的保證太麻煩了。

+0

Django的'QueryDict'覆蓋'__setitem__','collections.OrderedDict'不會執行協作式繼承。由此「微優化」導致的問題示例:https://stackoverflow.com/questions/23662247/can-i-make-django-querydict-preserve-ordering#comment78727560_41798570 – wim

相關問題