我有这个基类和子类:
class Event:
def __init__(self, sr1=None, foobar=None):
self.sr1 = sr1
self.foobar = foobar
# Event class wrappers to provide syntatic sugar
class TypeTwoEvent(Event):
def __init__(self, level=None):
self.sr1 = level
稍后,当我尝试检查TypeTwoEvent
示例的foobar
属性时,我得到一个异常。例如,在REPL测试:
>>> event = TypeTwoEvent()
>>> event.foobar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'TypeTwoEvent' object has no attribute 'foobar'
我认为基类的属性将被子类继承,创建子类的示例将示例化基类(从而调用其构造函数)。因此,我希望foobar
属性值默认为None
。
为什么TypeTwoEvent
示例没有foobar
属性,尽管Event
示例有?
5条答案
按热度按时间gywdnpxw1#
子类应为:
因为
__init__
被重写,所以基类的__init__
代码只有在显式请求时才会运行。尽管
__init__
的名字很奇怪,但它并没有被特别对待。它在对象创建后被自动调用;但除此之外,它就是一个普通的方法,并且适用普通的继承规则。是调用方法的父版本的语法。使用
*args
和**kwargs
允许我们catch additional arguments passed to__init__
和pass them to the parent method;这样,当创建TypeTwoEvent
时,可以为foobar
指定一个值,沿着特定于基类的任何其他值。5us2dqdw2#
您正在重写父类的构造函数(
__init__
)。要扩展它,需要使用super()
调用显式调用父对象的构造函数。注意
super
调用 * 不 * 总是在子类中__init__
方法的顶部。它的位置取决于你的情况和逻辑。wgxvkvu93#
创建示例时,将调用其
__init__
方法。在这种情况下,它是TypeTwoEvent.__init__
。超类方法将不会被自动调用,因为这会造成极大的混乱。您应该从
TypeTwoEvent.__init__
调用Event.__init__(self, ...)
(或者使用super
,但如果您不熟悉它,请先阅读它,以便您知道您在做什么)。f4t66c6m4#
需要从继承类的
__init__
方法调用基类的__init__
方法。请参阅here了解如何执行此操作。
lawou6xi5#
我也遇到过同样的问题,但在我的例子中,我把
super().__init__()
放在了派生类的底部,这就是为什么它不起作用。因为我试图使用未初始化的属性。