在Python 3中,超类可以多态地调用子类的构造函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Python 3中,超类可以多态地调用子类的构造函数相关的知识,希望对你有一定的参考价值。

我想在类(copy)中创建方法(比如Parent),它将返回调用它的类或子类的对象。我想要type(x) == type(x.copy())

我尝试过的方法都不令人满意。

  • 使用超类构造函数返回超类(make sense,但我认为值得一试)。
  • 在超类使用的每个子类中创建一个函数init_me,但这会破坏继承的目的。
  • 我开始探索__new____init__,但很快就决定Python必须有更好的方法。

示例代码

class Parent(object):
    def __init__(self, p1=p1_default, p2=p2_default, p3=p3_default):
        ...   # common stuff
        self._special_suff()
    def copy_works_if_subclass_does_extra(self):
        return self.init_me()
    def copy_only_does_superclass(self):
        return Parent()
    def copy_with_init(self):
        return self.__init__()
    def whoami(self):
        print('I am just a parent')

class Dad(Parent):
    def _special_stuff():
        ...     # Dad special stuff
        return 
    def whoami(self):
        print('I am a dad')
    def init_me(self):
        return Dad()

class Mom(Parent):
    def _special_stuff():
        ...     # Mom special stuff
        return 
    def whoami(self):
        print('I am a mom')
答案

如果我理解正确,你试图在你的基类中编写一个copy方法,当在派生类的实例上调用时它仍然可以工作。这可以使用,但是如果您的子类只需要与基类相同的参数集,那么这很容易。如果他们的__init__方法需要不同的参数,那么每个派生类都需要单独的copy方法。

这是一个如何工作的简单示例。诀窍是调用type(self)来获取正确的类,然后使用适当的构造函数参数调用该类以获取新实例:

class Base(object):
    def __init__(self, arg1, arg2, arg3):
        self.attr1 = arg1
        self.attr2 = arg2
        self.attr3 = arg3

    def copy(self):
        cls = type(self)
        return cls(self.attr1, self.attr2, self.attr3)

class Derived(Base):
    def __init__(self, arg1, arg2, arg3):
        super().__init__(arg1, arg2, arg3)
        self.some_other_attr = "foo"

在实践中,这往往不起作用,因为Derived类通常需要额外的参数来设置其额外属性。在这种情况下可能有效的选项是使用the copy module而不是编写自己的copy方法。函数copy.copy将能够复制许多Python实例,而无需任何特殊支持。

另一答案

你的事情太复杂了。在子类上实现简单构造函数的最小示例:

import copy

class Parent():
    def whoami(self):
        print('Just a parent')
    def __init__(self, name):
        self.name = name
    def copy(self):
        # Maybe copy.deepcopy instead
        return copy.copy(self)


class Dad(Parent):
    def whoami(self):
        print('I am a dad')
    def __init__(self, name):
        super().__init__(name)
        self.gender = 'Male'

如果你不需要,你甚至不需要Python中的构造函数。或者你可以在超类上有一个而在孩子上没有任何东西。

一些用法:

>>> dad = Dad("Clark Griswold")
>>> dad.name
'Clark Griswold'
>>> dad.whoami()
I am a dad
>>> isinstance(dad, Dad)
True
>>> isinstance(dad, Parent)
True
>>> type(dad.copy()) == type(dad)
True

以上是关于在Python 3中,超类可以多态地调用子类的构造函数的主要内容,如果未能解决你的问题,请参考以下文章

Java随笔一

2016年4月2日_JAVA学习笔记_下午

Java多态如何调用子类对象的超类方法

python--继承和多态

Java基础之类的特性和接口

JavaSE复习_3 继承