35

我有以下基类和子类:

class Event(object):
    def __init__(self, sr1=None, foobar=None):
        self.sr1 = sr1
        self.foobar = foobar
        self.state = STATE_NON_EVENT

# Event class wrappers to provide syntatic sugar
class TypeTwoEvent(Event):
    def __init__(self, level=None):
        self.sr1 = level
        self.state = STATE_EVENT_TWO

在我的代码中,我正在检查一个TypeTwoEvent类的实例,检查我知道基类中存在的字段 - 我希望它默认为 value None。但是,我的代码引发了以下异常:

AttributeError:“TypeTwoEvent”对象没有属性“foobar”

我的印象是基类字段将由子类继承,并且创建子类的实例将实例化基类(并因此调用其构造函数)......

我在这里想念什么?为什么没有TypeTwoEvent属性foobar- 当派生它的基类有foobar属性时?

4

5 回答 5

37

你的子类应该是:

class TypeTwoEvent(Event):

    def __init__(self, level=None, *args, **kwargs):
        super(TypeTwoEvent, self).__init__(*args, **kwargs)
        self.sr1 = level
        self.state = STATE_EVENT_TWO

因为你重写了__init__方法,所以如果你想让父行为发生,你需要调用父方法。

请记住,__init__尽管它的名字很奇怪,但这并不是一种特殊的方法。它只是对象创建后自动调用的方法。否则它是一个普通的方法,并且应用普通的继承规则。

super(ClassName, self).__init__(arguments, that, goes, to, parents)

是调用方法的父版本的语法。

对于*argsand **kwargs,它只是确保我们捕获传递给的所有附加参数__init__并将其传递给父方法,因为您的子方法签名没有这样做,而父方法需要这些参数才能工作。

于 2012-04-22T14:18:11.177 回答
4

您正在覆盖__init__父类的构造函数 ( )。要扩展它,您需要通过调用显式调用父级的构造函数super()

class TypeTwoEvent(Event):
    def __init__(self, level=None, **kwargs):
        # the super call to set the attributes in the parent class
        super(TypeTwoEvent, self).__init__(**kwargs)
        # now, extend other attributes
        self.sr1 = level
        self.state = STATE_EVENT_TWO

请注意,super调用并不__init__总是位于子类中方法的顶部。它的位置取决于你的情况和逻辑。

于 2012-04-22T14:11:05.450 回答
2

创建实例时,将__init__调用其方法。在这种情况下,即TypeTwoEvent.__init__。超类方法不会被自动调用,因为那会非常混乱。

您应该调用Event.__init__(self, ...)from TypeTwoEvent.__init__(或使用super,但如果您不熟悉它,请先阅读它,以便您知道自己在做什么)。

于 2012-04-22T14:11:00.590 回答
1

需要从继承类__init__的方法中调用基类的__init__方法。

请参阅此处了解如何执行此操作。

于 2012-04-22T14:09:37.877 回答
0

我也有这个问题,但我已经把super().__init__()我的派生类放在了底部,这就是它不起作用的原因。因为我尝试使用未初始化的属性。

于 2017-07-23T16:30:33.493 回答