我试图避免在两个类的克隆方法中重复相同的代码,一个继承自另一个类。我目前的方法是将两个类共有的代码放在基类的(非静态)克隆方法中,并从扩展类中调用它。为此,我试图将扩展类的构造函数传递给基类,以便可以在那里调用它。以下是我目前正在做的简化示例:
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__
?
您认为哪种方式更好?
答案 0 :(得分:5)
虽然__init__()
通常被称为Python中的构造函数,但它实际上并不是。它将实例作为self
参数传入,并返回None
。该实例之前由__new__()
方法构造,该方法是实际的构造函数。但是,您不应该传递对__new__
的引用。传递类型本身更容易,更直接。
编辑:实现clone
方法的正确方法是另一种方法:坚持通常的Python协议,并实施__getstate__()
和__setstate__()
你的实例。然后,您可以使用copy
模块中的函数正确克隆实例。
答案 1 :(得分:2)
您的基类克隆方法是多余的。从任何上下文调用self.__init__()
将遵循对象的特定实例中的MRO,这意味着在clone()
的实例上调用C
将从C.__init__()
中的代码调用S
{1}}未指定明确使用c.__init__()
。
如果您想要做的是能够自定义clone()
而不必创建一个全新的类,或者根据其他因素有不同的行为,我建议您查看工厂/构建器模式。 / p>
此外,专门针对clone()
类型的操作,您可能希望查看重载__copy__()
,__getstate__()
和__setstate__()
并使用copy.copy()
和{ {1}}而不是实现新的辩证元素。