在面向对象编程中,经常需要创建具有相同属性和方法的不同对象。一种常见的方法是使用 __init__ 方法来初始化对象。
但是,有时我们需要在 __init__ 方法中接收新值或已有实例。例如,我们可能有一个 Foobar 类,它具有一个 value 属性。我们希望 Foo 和 Bar 类可以使用 Foobar 的实例或使用新值来创建 Foobar 实例。
以下是我们希望实现的代码:
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 参数。
但是,这段代码存在冗余,需要在 Foo 和 Bar 类中重复相同的代码。因此,我们希望找到一种方法来消除这种冗余。
2. 解决方案
方法一
一种解决方案是使用 __new__ 方法来创建对象。__new__ 方法在 __init__ 方法之前调用,它负责创建对象并返回对象引用。
我们可以通过重写 __new__ 方法来实现我们的目标。以下是重写的 __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__ 方法中,我们首先检查 value 是否是 Foobar 类的一个实例。如果是,则直接返回该实例。否则,我们调用 object.__new__(cls, value) 来创建 Foobar 实例并返回该实例。
这样,我们就消除了 Foo 和 Bar 类中冗余的代码。
方法二
另一种解决方案是使用 mixin 类。mixin 类是一个提供某些功能的类,它可以被其他类继承。
我们可以创建一个 FoobarMixin 类来提供 __init__ 方法的逻辑。以下是 FoobarMixin 类的代码:
class FoobarMixin(object):
def __init__(self, **kwargs):
foobar = kwargs['foobar']
if isinstance(foobar, Foobar):
self.foobar = foobar
else:
self.foobar = Foobar(foobar)
FoobarMixin 类中的 __init__ 方法接受一个 **kwargs 参数,它是一个关键字参数字典。__init__ 方法从 **kwargs 参数中提取 foobar 参数,然后检查 foobar 参数是否是一个 Foobar 实例。如果是,则直接将 foobar 参数赋值给 self.foobar 属性。否则,__init__ 方法调用 Foobar(foobar) 来创建 Foobar 实例并将其赋值给 self.foobar 属性。
然后,我们可以让 Foo 和 Bar 类继承 FoobarMixin 类。以下是 Foo 和 Bar 类的代码:
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 和 Bar 类中冗余的代码,并且实现了我们的目标。
我们也可以使用以下代码来创建 Foo 和 Bar 的实例:
foo = Foo('foo', foobar='foobar')
bar = Bar('bar', foobar=Foobar('foobar'))
输出结果如下:
foo <__main__.Foobar object at 0x7fa0fedf6050>
bar <__main__.Foobar object at 0x7fa0fedeaf10>