2016-09-13 8 views
4

私たちは、多重継承を使用することによって自明OrderedCounterを作成することができます:私が間違っている場合なぜOrderedDictはsuperを使用しませんか?

>>> 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を使用します。まず

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が最初に来たとレイモンドは、後でそれを変更する気にしませんでしたので、それができると思った:

は、しかし同僚は最近OrderedDictdoesn't使用スーパーことを、私の驚きに、指摘しましたそれはsuperの前のOrderedDictのようです。

OrderedDictはなぜdict.__setitem__と明示的に呼びますか?

なぜそれがkwargである必要がありますか?ダイヤモンドの継承状況でOrderedDictを使用すると、mroの次の行に委譲するのではなく、直接親クラスに渡すので、これは問題を引き起こしませんか?

答えて

0

これは、微小最適化です。 dict_setitem引数を検索すると、dict.__setitem__またはsuper().__setitem__を検索するよりも少し速くなります。

__setitem__をオーバーライドする別のクラスがある場合は、複数の継承に問題が生じる可能性がありますが、OrderedDictはそのような種類のダイヤモンド構造のメソッドオーバーライド用に設計されていません。 OrderedDictをサポートするためには、注文情報がdict構造と矛盾している間に別のクラスのメソッドがOrderedDictのインデックスを作成しようとすると、どのメソッドが見えるかを非常に慎重に保証する必要があります。そのような保証は作るのが面倒です。

+0

Djangoの 'QueryDict'は' __setitem__'をオーバーライドし、 'collections.OrderedDict'は協調継承を行いません。この「マイクロ最適化」によって引き起こされる問題の例:https://stackoverflow.com/questions/23662247/can-i-make-django-querydict-preserve-ordering#comment78727560_41798570 – wim

関連する問題