继承类中的python __init__方法

Posted

技术标签:

【中文标题】继承类中的python __init__方法【英文标题】:python __init__ method in inherited class 【发布时间】:2011-08-03 22:22:25 【问题描述】:

我想给子类一些额外的属性,而不必显式调用新方法。那么有没有办法给继承的类一个__init__类型的方法而不覆盖父类的__init__方法呢?

我编写下面的代码纯粹是为了说明我的问题(因此属性命名不佳等)。

class initialclass():
    def __init__(self):
        self.attr1 = 'one'
        self.attr2 = 'two'    

class inheritedclass(initialclass):
    def __new__(self):
        self.attr3 = 'three'

    def somemethod(self):
        print 'the method'


a = inheritedclass()

for each in a.__dict__:
    print each

#I would like the output to be:
attr1
attr2
attr3

谢谢

【问题讨论】:

在派生类构造函数中调用initialclass.__init__。但是,attrX 的顺序不保证。 不要覆盖__new__,除非你确切地知道它做了什么以及为什么你需要摆弄它。你大概不知道。这不是__init__ 的别名。它比我们通常关心的级别高出三个级别,尤其是初学者。 注意__new__ 的参数是selfclass,而不是self,因为它是一个隐式类方法。所以在你的例子中,你实际上是在设置类属性inheritedclass.attr3,而不是你想象的self.attr3 【参考方案1】:

据我所知,这是不可能的,但是您可以调用超类的 init 方法,如下所示:

class inheritedclass(initialclass):
    def __init__(self):
        initialclass.__init__(self)
        self.attr3 = 'three'

【讨论】:

太棒了,我一直在想办法解决这个问题 这样做有什么缺点吗?【参考方案2】:

只需使用super 调用父母的__init__

class inheritedclass(initialclass):
    def __new__(self):
        self.attr3 = 'three'
        super(initialclass, self).__init__()

我强烈建议遵循 Python 的命名约定并以大写字母开始一个类,例如InheritedClassInitialClass。这有助于快速区分类与方法和变量。

【讨论】:

具体来说,使用super(DerivingClass, self).__init__()。或者只是 super().__init__() 在 Python 3 中。编辑:-1 因为 1.super 需要继承(!)类和 2.你不必要地覆盖 __new__,而现在的代码实际上是不正确的(它创建了一个属性attr3)。 这适用于 new 方法,但正如lazyr 告诉我的(正确地)我不应该使用 new,我认为正确的答案是我是 yexo 的。不过谢谢! @Anake Credit 应得的信用,是@delnan 告诉你不要使用__new__,我只是解释了你的代码实际上做了什么。顺便说一句,__new__必须返回它的类的一个实例,如果你实现它的话。在上面的答案以及您的代码中,inheritedclass() is None!换句话说,它根本不起作用。 (我错误地给了这个答案一个赞成票,没有正确阅读代码,现在我无法更改它:(.)【参考方案3】:

首先你要混合__init____new__,它们是different things。 __new__ 不接受实例 (self) 作为参数,它接受类 (cls)。 至于您问题的主要部分,您要做的是使用super 调用超类'__init__

您的代码应如下所示:

class initialclass(object):
    def __init__(self):
        self.attr1 = 'one'
        self.attr2 = 'two'    

class inheritedclass(initialclass):
    def __init__(self):
        self.attr3 = 'three'
        super(inheritedclass, self).__init__()

【讨论】:

谢谢,我对新方法的错误。我正在尝试使用 super,但我不断收到此错误:TypeError: super() argument 1 must be type, not classobj. (我也复制并粘贴了您的代码) @Anake:initialclass需要继承object(class initialclass(object)),否则就是老派,只不过是让人头疼的过去遗物而已,应该避免。【参考方案4】:

这非常简单。定义一个新的__init__方法,并在开头调用父级的__init__

# assuming a class Base, its __init__ takes one parameter x

class Derived(Base):
    def __init__(self, x, y):
        # whatever initialization is needed so we can say Derived is-a Base
        super(Derived, self).__init__(x)
        # now, add whatever makes Derived special - do your own initialization
        self.y = y

在 Python 3 中,您不必(因此为简单起见可能不应该)显式继承 object 或将类和 self 传递给 super

【讨论】:

【参考方案5】:

只要从父级的init中调用一个指定的方法,如果存在的话:

class initialclass():
    def __init__(self):
        self.attr1 = 'one'
        self.attr2 = 'two'  
        if hasattr(self, 'init_subclass'):
            self.init_subclass()

class inheritedclass(initialclass):
    def init_subclass(self):
        self.attr3 = 'three'

【讨论】:

虚拟 -1。不需要在父类中做任何额外的工作,更不用说hasattr 和额外的方法。您可以简单地定义一个新的__init__,使用super 调用父级的__init__ @delnan 我知道这一点,但问题是“有没有办法给继承的类一个 init 类型的方法 它不会覆盖父类的 init 方法 ”。我提供了这样一种方式。这有一个额外的好处,即为从其他子类方法调用子类 init 提供一个入口点。 这就是为什么它是虚拟的。我知道这是 OP 要求的,但 OP 询问“我如何使用锤子来做到这一点?”答案是“你用螺丝刀”。 @delnan 我认为 OP问的是,借用你的比喻,“当我不想使用螺丝刀时,如何使用锤子来做到这一点? ”。我假设覆盖包括扩展,因为在我看来,扩展方法只是一种被覆盖的方法——它以某种方式调用父方法。我错误地认为,他似乎知道如何扩展方法。顺便说一句,不是所有的python方法都是虚拟的吗?我从来没有听过任何人谈论 python 中的虚拟方法。 关于 Python 方法是虚拟的,您是正确的,-1 是虚拟的 ;)【参考方案6】:
class initialclass:
        def __init__(self):
                self.attr1 = 'one'
                self.attr2 = 'two'
class inheritedclass(initialclass):
        def __init__(self):
                super().__init__()
                self.attr3 = 'three'
        def somemethod(self):
                print (self.attr1, self.attr2, self.attr3)
a=inheritedclass()
a.somemethod()

 1. List item

【讨论】:

以上是关于继承类中的python __init__方法的主要内容,如果未能解决你的问题,请参考以下文章

python中的继承关系详解

面对对象之继承 | Python

python新式类中的__new__方法与__init__方法

面向对象之继承——python篇

关于 python 类与继承中方法调用 的 一个小知识点记录

Python类中的__new__和__init__的区别