2

2 つのクラスのクローン メソッドで同じコードを繰り返さないようにしています。一方は他方から継承しています。私の現在のアプローチは、両方のクラスに共通するコードを基本クラスの (非静的) clone メソッドに入れ、それを拡張クラスから呼び出すことです。これを行うために、拡張クラスのコンストラクターを基本クラスに渡して、そこで呼び出すことができるようにしています。これは、私が現在行っていることの簡単な例です。

class S(object):
    """Base class"""
    def __init__(self):
        self.a = 0

    def clone(self, constructor=None):
        if constructor is None:
            constructor = self.__init__
        cloned = constructor()
        # Expecting: cloned.a = 1, cloned.b = 7

        assert cloned is not None  # raises AssertionError
        cloned.a = self.a  # Set a to 2
        return cloned

class C(S):
    """Child class, extending Base"""
    def __init__(self):
        self.a = 1
        self.b = 7

    def clone(self):
        cloned = super(C, self).clone(self.__init__)
        # Expecting: cloned.a = 2, cloned.b = 7

        cloned.b = self.b  # Set b to 8
        return cloned

if __name__ == '__main__':
    c1 = C()
    c1.a = 2
    c1.a = 8
    c2 = c1.clone()

この時点での私の質問は次のとおりです。

  • 基底クラスNoneのメソッドを呼び出したときに返されるのはなぜですか?clone

  • またはを使用して、メソッドを使用するためにクラスにバインドする必要があり ますtypes.MethodType__get__?

  • より良い方法として何を提案しますか?

4

2 に答える 2

5

__init__()Python ではコンストラクターと呼ばれることがよくありますが、実際にはそうではありません。self引数として渡されたインスタンスを取得し、を返しますNone。インスタンスは__new__()、実際のコンストラクターであるメソッドによって以前に構築されます。ただし、への参照を渡すべきではありません__new__。型自体を渡す方がはるかに簡単で簡単です。

編集: メソッドを実装するための正しいアプローチcloneは、さらに別のものです。通常の Python プロトコルに固執し、インスタンスに and を実装__getstate__()__setstate__()ます。次に、モジュールの関数を使用してcopy、インスタンスを正しく複製できます。

于 2012-07-23T13:39:50.390 に答える
2

基本クラスの clone メソッドは冗長です。任意のコンテキストからの呼び出しself.__init__()は、オブジェクトの特定のインスタンスからの MRO に従います。つまりclone()、インスタンスのC呼び出しは、使用を明示的に指定せずC.__init__()にコードから呼び出されます。Sc.__init__()

ただし、まったく新しいクラスを必ずしも作成せずにカスタマイズできるようにしたい場合clone()、または他の要因に応じて異なる動作をしたい場合は、ファクトリ/ビルダー パターンを検討することをお勧めします。

また、特にclone()型操作については、新しい弁証法的要素を実装する代わりに__copy__()、 、__getstate__()、およびを__setstate__()オーバーロードすることを検討することをお勧めします。copy.copy()copy.deepcopy()

于 2012-07-23T13:44:38.667 に答える