2

我试图避免在两个类的克隆方法中重复相同的代码,一个继承自另一个。我目前的方法是将两个类共有的代码放在基类的(非静态)克隆方法中,并从扩展类中调用它。为此,我试图将扩展类的构造函数传递给基类,以便可以在那里调用它。这是我目前正在做的一个简化示例:

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.MethodTypeor __get__

  • 你会建议什么更好的方式去?

4

2 回答 2

5

虽然__init__()在 Python 中通常称为构造函数,但实际上并非如此。它获取作为参数传入的实例self,然后返回None. 该实例是由该__new__()方法较早构造的,该方法是实际的构造函数。但是,您不应该传递对 的引用__new__。传入类型本身更容易、更直接。

编辑:实现方法的正确clone方法是另一种方法:坚持通常的 Python 协议,并在您的实例上实现__getstate__()和。__setstate__()然后,您可以使用copy模块中的功能正确克隆您的实例。

于 2012-07-23T13:39:50.390 回答
2

您的基类克隆方法是多余的。从任何上下文调用self.__init__()都将遵循对象特定实例的 MRO,这意味着调用clone()的实例将从代码C调用,而无需明确指定使用。C.__init__()Sc.__init__()

如果您想要做的是能够自定义clone()而不必创建一个全新的类,或者根据其他因素具有不同的行为,我建议您查看工厂/构建器模式。

此外,特别是对于clone()类型操作,您可能希望查看重载__copy__()__getstate__()__setstate__()并使用copy.copy()andcopy.deepcopy()而不是实现新的辩证元素。

于 2012-07-23T13:44:38.667 回答