2012-02-24 6 views
14

私は内蔵のlistタイプなので、私はこれを書いたにいくつかの属性を追加したい:Python:組み込みのリストタイプから継承するにはどうすればよいですか?

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のような不変型についても同じですか?

+0

参照[この質問](http://stackoverflow.com/questions/3945940/what-to-consider-before-subclassing-list)いくつかのためにサブクラス化リストの主題に関する議論、そしてそれがしばしばあなたが望むものではない方法について説明します。 (collections.MutableSequenceがある場合は、より良いルートかもしれません:[Alex Martelli](http://stackoverflow.com/a/3488283/487339)を読んでください)。 – DSM

+0

可能な複製:http://stackoverflow.com/q/4093029/596361 –

答えて

19

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

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

はまた、私はこのケースでsuper()を使用しないことをお勧めしていることに注意してください。あなたはlist.__init__()に電話したいと思っています。

+0

ああ、私はスーパークラスの '__init__'を呼び出すのを忘れていました。しかし、不変型はどうですか?あるいは、 '__new__'をいつオーバーライドするべきかについて一般的なルールがありますか? –

+0

@ PJ.Hades:必要に応じて上書きします。これは、一般に、不変データの構成に影響を与える必要がある場合です。 'tuple'をサブクラス化してさらにメソッドや属性を追加する場合は、' __new __() 'を上書きする必要はありません。不確かな場合は、ドキュメントを読んでください。 –

+0

@SvenMarnach、 'self.append( 'FirstMen')' - 'FirstMen'は' list'や 'MyList'のどこに追加されますか? –

8

まず、__new__を理解するための練習としてこれをやっていますか?そうでなければ、あなたがやろうとしていることをやるより良い方法がほとんどあります。ここで達成したいことを説明できますか?言っ

は、ここにあなたの例では何が起こっているかです:

  1. あなたはMyList([1,2,3,4])
  2. を呼び出すこの最初の実装では、これが要素と、MyListの新しいインスタンスを返しますlist.__new__(MyList,[1,2,3,4]) を呼び出しMyList.__new__(MyList,[1,2,3,4])
  3. を起動します。 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

+0

私はこの問題の原因を知っていました。あなたの説明をありがとう:) –

+0

'MyList .__ init __()' *が 'list .__ init __()'を呼び出した場合、リストの内容を '[1、2、3、4]'、 '' FirstMen''はなくなります。 –

関連する問題