继承-使用类方法创建类的新实例的正确方法

时间:2019-01-11 16:07:39

标签: python python-3.x

我是上帝(或进化,或您所信仰的任何事物)。我正在尝试使用Python创建所有生物。

我定义了一个能够“复制”的类,即能够创建其自身的新实例(忽略它看起来更像是克隆而不是复制的事实,这是针对地球的Beta版): / p>

class Animal:
    def __init__(self, **kwargs):
         self.characteristics = kwargs

    def reproduce(self):
        return Animal(**self.characteristics)

这在基类的情况下很好用,但是当我创建一个继承自Animal的类时会发生什么呢?

class Fox (Animal):
    def __init__ (self, **kwargs):
        self.color = 'red'
        super().__init__(dict(self.color, **kwargs))

如果Fox尝试reproduce,我将拥有类型Animal而不是Fox的实例(即使它仍然具有颜色'red' )。

我可以重载狐狸能够重现的方法:

def reproduce(self):
     return Fox(self.characteristics)

但是,对于我定义的每个新生物,我都必须这样做!

如何创建一个类,使我所有的生物都可以从中继承,因此当它们reproduce被创建时,是同一类的对象吗?这样我可以确定:

parent = Fox()
child = parent.reproduce()
assert type(parent) == type(child)

我知道我可以使用type来使reproduce返回type(self)(self.characteristics)self.__class__(**self.characteristics),但对我来说似乎并不那么强。有更合适的方法吗?

1 个答案:

答案 0 :(得分:3)

注意:您从一个子类采用不同数量的参数的地方更改了问题。如果您坚持这样的设计,那么您就别无选择,只能覆盖reproduce(),因为没有一致的API可以创建“当前类”的新实例。

如果要标准化类API,则还可以标准化创建新实例,这时您可以编写一个reproduce()方法,只需要type(self)来引用当前类,然后继续来创建此类的新实例。

请注意,必须为每个子类编写新的reproduce()方法也是一个不错的选择,因为这是委派创建专门子类的新实例的好方法。您赋予每个子类处理复制细节的责任。

但是,如果您不想这样做,则可以将责任从子类中删除,然后将其放在基类中,此时,如何创建实例的基本 design 是该基层的责任。

这两个选项之间当然有中间立场,但是所有这些都归结为某种形式的授权。您可以让基类提供某种结构,详细说明创建实例时应复制哪些属性,您可以让子类实现__copy__ or __deepcopy__ hooks来通过copy.copy()或{{1 }}电话等

您更新的问题结构只是该授权的另一个示例;您添加了copy.deepcopy()字典,因此子类负责保持该字典的更新,以便基类可以按以下方式实现复制:

characteristics

那是完美的Python语言,但更多的是,因为这是一个不错的OO设计,您在其中进行了选择,以最小化负责哪些子类,并让基类尽可能多地进行再现。