Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python3中,超类能否以多态方式调用子类';s构造函数_Python_Python 3.x_Inheritance_Constructor_Polymorphism - Fatal编程技术网

在Python3中,超类能否以多态方式调用子类';s构造函数

在Python3中,超类能否以多态方式调用子类';s构造函数,python,python-3.x,inheritance,constructor,polymorphism,Python,Python 3.x,Inheritance,Constructor,Polymorphism,我想在类(Parent)中创建一个方法(比如copy),该方法将返回调用它的类或子类的对象。我想要type(x)==type(x.copy()) 我尝试的方法都不令人满意 使用超类构造函数返回超类(有意义,但我认为值得一试) 在超类使用的每个子类中创建一个函数init_me,但这违背了继承的目的 我开始探索\uuuuu new\uuuu和\uuuuu init\uuuuu,但很快决定Python必须有更好的方法 示例代码 class Parent(object): def __ini

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

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

  • 使用超类构造函数返回超类(有意义,但我认为值得一试)
  • 在超类使用的每个子类中创建一个函数
    init_me
    ,但这违背了继承的目的
  • 我开始探索
    \uuuuu new\uuuu
    \uuuuu init\uuuuu
    ,但很快决定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')

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

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

如果我理解正确,那么您正在尝试在基类中编写一个
copy
方法,该方法在派生类的实例上被调用时仍然有效。这可以实现,但只有当您的子类只需要与基类相同的参数集时,这才容易实现。如果他们的
\uuuu init\uuuu
方法需要不同的参数,则需要为每个派生类使用单独的
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"

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

我正在尝试一种可能是死胡同的设计方法。超类构造函数有几个参数。对于所有继承的类,这些参数都是相同的。因此,我们的想法是让子类实现一个“私有”方法,用于进行专门的构造。多态分派将处理子类中的变化。然后我实现了返回子类型所需的基本函数(不仅仅是示例中的
copy
)。过于复杂化?也许。但是在改变设计之前,我想检查一下我的选择。你能在最初的帖子中提供一个专业结构的例子吗。我不确定我是否理解。我最后的评论是真实的,但有误导性。主要的挑战是重复使用
copy
功能。我希望
Dad().copy
Mom.copy()
在超类中使用相同的代码,但在这两种情况下都返回子类。那么,如何使超类基代码足够聪明,能够使用子类的构造函数呢?我在我的示例中添加了一个
copy
。不确定您的将如何工作。
cls=type(self)
后跟
返回cls(…)
回答了我的问题。我的印象是,如果我需要使用
类型
,那么我需要重新考虑我的设计。我不认为使用
类型
本质上就是糟糕的设计。有一些糟糕的代码依赖于它(特别是初学者代码,如果type(foo)=Bar而不是使用
isinstance
),那么在需要处理类对象及其实例时使用
type
是完全合理的。它是Python的基本内省工具之一。