4

次のようなパターンがあります。

class Foobar(object):  # instances of this class will be referenced by others
    def __init__(self, value):
        self.value = value

class Foo(object):
    def __init__(self, value, foobar)
        self.value = value
        if isinstance(foobar, Foobar):
            self.foobar = foobar
        else:
            self.foobar = Foobar(foobar)

class Bar(object):
    def __init__(self, value, foobar)
        self.value = value
        if isinstance(foobar, Foobar):
            self.foobar = foobar
        else:
            self.foobar = Foobar(foobar)

これによりFoo、 とBarは新しい値 ( を作成するためFoobar) または の既存のインスタンスのいずれかを引数Foobarとして受け取ることができます。foobar


この冗長なコードを取り除きたい:

# ...
        if isinstance(foobar, Foobar):
            self.foobar = foobar
        else:
            self.foobar = Foobar(foobar)

私は次のことを検討しましたが、 の無限再帰のために機能しませんFoobar.__new__():

class Foobar(object):
    def __new__(cls, value):
        if isinstance(value, cls):
           return value
        else:
           return Foobar(value)
    def __init__(self, value):
        self.value = value

class Foo(object):
    def __init__(self, value, foobar)
        self.value = value
        self.foobar = Foobar(foobar)

class Bar(object):
    def __init__(self, value, foobar)
        self.value = value
        self.foobar = Foobar(foobar)

に渡される値に応じて、クラスが新しいインスタンスを作成したり__init__、既存のインスタンスを使用できるようにする最善の方法は何ですか?

4

2 に答える 2

4

基本クラスを呼び出すことで、再帰を取り除くことができます__new__()

class Foobar(object):
    def __new__(cls, value):
        if isinstance(value, cls):
           return value
        else:
           return object.__new__(cls, value)
    def __init__(self, value):
        self.value = value

の最初のパラメータ__new__()は ではなくクラスであることに注意してくださいself

とはいえ、これが有用なパターンであるとは確信していません。一般に、コンストラクターでインスタンスを受け入れ、オブジェクトの構築は呼び出し元のコードに任せることをお勧めします。正しいことを行う魔法はしばしば便利に見えますが、通常、価値がある以上に将来的に多くの問題を引き起こします。

于 2013-06-27T16:46:48.420 に答える
1

別のオプションは、重複したコードを mixin クラスで除外することです...

class Foobar(object):
    def __init__(self, value):
        self.value = value

class FoobarMixin(object):
    def __init__(self, **kwargs):
        foobar = kwargs['foobar']
        if isinstance(foobar, Foobar):
            self.foobar = foobar
        else:
            self.foobar = Foobar(foobar)

class Foo(FoobarMixin):
    def __init__(self, value, **kwargs):
        super(Foo, self).__init__(**kwargs)
        self.value = value
        print self.value, self.foobar

class Bar(FoobarMixin):
    def __init__(self, value, **kwargs):
        super(Bar, self).__init__(**kwargs)
        self.value = value
        print self.value, self.foobar

foo = Foo('foo', foobar='foobar')
bar = Bar('bar', foobar=Foobar('foobar'))

...印刷...

foo <__main__.Foobar object at 0x7fa0fedf6050>
bar <__main__.Foobar object at 0x7fa0fedeaf10>
于 2013-06-27T17:17:03.070 に答える