继承类中的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__
的参数是self
的class,而不是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 的命名约定并以大写字母开始一个类,例如InheritedClass
和 InitialClass
。这有助于快速区分类与方法和变量。
【讨论】:
具体来说,使用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新式类中的__new__方法与__init__方法