2011-01-31 13 views
7

を異なるように見える:継承の行動は、誰かが次の動作を説明でき

class derivedset1(frozenset): 
    def __new__(cls,*args): 
     return frozenset.__new__(cls,args) 

class derivedset2(set): 
    def __new__(cls,*args): 
     return set.__new__(cls,args)  

a=derivedset1('item1','item2') # WORKS 
b=derivedset2('item1','item2') # DOESN'T WORK 

Traceback (most recent call last): 
    File "inheriting-behaviours.py", line 12, in <module> 
    b=derivedset2('item1','item2') # DOESN'T WORK 
TypeError: derivedset2 expected at most 1 arguments, got 2 

これは、のコンストラクタのは不可能であるのに対し、あなたが凍結されたセットのコンストラクタを変化させることができることを私には驚くべきことです可変セット。 から

+1

興味深いデータポイント: 'b = derivedset2([item1 '、' item2 '])'は動作します。 –

答えて

4

__new__()clsのインスタンスを返す場合、新しいインスタンスの__init__()メソッドは、selfが新しいインスタンスであり、残りの引数が同じである場合、__init__(self[, ...])ように呼び出されます__new__()に渡されました。

set.__init__は、最初のセット内容を指定する繰り返し可能な1つの引数をとります。そのため、あなたはすべての追加の引数を取り、初期設定値としてそれらを提供する独自の初期化子を追加する必要があります:あなたは__init__を上書きして、オブジェクトキャッシュを実装する場合を除き、__new__の実施を控えるべきです

class derivedset2(set): 
    def __new__(cls,*args): 
     return set.__new__(cls,*args) 

    def __init__(self, *initial_values): 
     set.__init__(self, initial_values) 

お知らせ、シングルトン、または同様の奇妙なもの。 frozensetのサブクラス化は、frozensetです。オブジェクトキャッシュから利益が得られます。つまり、Pythonインタプリタは同じ内容の2つのfrozensetオブジェクトに対して1つのfrozensetインスタンスしか必要としません。

特に、セマンティクスに互換性がない場合(この場合は、set([])derivedset2([])が全く異なる結果を返します)、組み込みクラスをサブクラス化しないようにしてください。

+3

'frozenset'が' __new__'を使う理由はキャッシュではなく、不変であるからです。要素が '__init__'によって消費された場合、クラスは多少変更可能でなければなりません。 'fs = frozenset .__ new __(frozenset)'は 'fs .__ init __([1、2、3])'で塗りつぶされた空の 'frozenset'を作成します。これは、サブクラス化のたびに毎回発生します。 –

+1

不変オブジェクトの値は、 '__new __()'メソッドの作成時点で確立されなければなりません - 後で '__init __()'メソッドでは実行できないからです。 – martineau

関連する問題