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)

这允许FooBar采用新值(创建 a 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

请注意, to 的第一个参数__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 回答