web-dev-qa-db-ja.com

Python:組み込みのリスト型から継承するにはどうすればよいですか?

組み込みのlist型にいくつかの属性を追加したいので、次のように記述しました。

class MyList(list):
    def __new__(cls, *args, **kwargs):
        obj = super(MyList, cls).__new__(cls, *args, **kwargs)
        obj.append('FirstMen')
        return obj

    def __init__(self, *args, **kwargs):
        self.name = 'Westeros'

    def king(self):
        print 'IronThrone'

if __name__ == '__main__':
    my_list = MyList([1, 2, 3, 4])
    print my_list

ただし、my_listには要素'FirstMen'のみが含まれます。 __new__がここで機能しないのはなぜですか?そして、listのような組み込み型からどのように継承する必要がありますか? strのような不変型についても同じですか?

16
PJ.Hades

list型は通常、その__init__()メソッド内でリストの実際の初期化を行います。これは、可変型の規則であるためです。不変の型をサブタイプ化する場合にのみ、__new__()を上書きする必要があります。リストをサブクラス化するときにcan__new__()を上書きしますが、ユースケースではそうする意味はあまりありません。 __init__()を上書きする方が簡単です。

_class MyList(list):
    def __init__(self, *args):
        list.__init__(self, *args)
        self.append('FirstMen')
        self.name = 'Westeros'
_

この場合、super()を使用しないことをお勧めします。ここでlist.__init__()を呼び出したいが、他には何も呼び出さない。

25
Sven Marnach

まず、___new___を理解するための演習としてこれを行っていますか?そうでない場合は、あなたがやろうとしていることを行うためのより良い方法がほぼ確実にあります。ここで達成したいことを説明していただけますか?

そうは言っても、あなたの例では次のようになっています。

  1. MyList([1,2,3,4])を呼び出します
  2. これは最初にMyList.__new__(MyList,[1,2,3,4])を呼び出します
  3. 実装はlist.__new__(MyList,[1,2,3,4])を呼び出します。これにより、要素のないMyListの新しいインスタンスが返されます。 _list.__new___はリストに入力されません。それは_list.__init___に任せますが、これは決して呼び出されません。
  4. ___new___メソッドは、空のMyListインスタンスに_'FirstMen'_を追加します。
  5. ___new___メソッドはMyListのインスタンスを返します。
  6. MyList.__init__([1,2,3,4])が呼び出されます。
  7. name属性を_'Westeros'_に設定します。
  8. 戻ります。
  9. インスタンスは_my_list_に割り当てられ、出力されます。

___new___の説明については、ここを参照してください: http://docs.python.org/reference/datamodel.html#basic-customization

8
Weeble