Python类继承:AttributeError:'[SubClass]'对象没有属性'xxx'

时间:2012-04-22 14:05:36

标签: python inheritance class-attributes

我有以下基类和子类:

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类的实例,检查我知道的基类中存在的字段 - 我希望它默认为值None。但是,我的代码引发了以下异常:

  

AttributeError:'TypeTwoEvent'对象没有属性'foobar'

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

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

5 个答案:

答案 0 :(得分:20)

你的子类应该是:

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)

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

对于*args**kwargs,它只是确保我们捕获传递给__init__的所有其他参数并将其传递给父方法,因为您的子方法签名没有这样做,父母需要这些论据才能发挥作用。

答案 1 :(得分:3)

您正在覆盖父类的构造函数(__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__方法的顶部。它的位置取决于你的情况和逻辑。

答案 2 :(得分:2)

创建实例时,会调用其__init__方法。在这种情况下,即TypeTwoEvent.__init__。不会自动调用超类方法,因为这会非常令人困惑。

您应该从Event.__init__(self, ...)致电TypeTwoEvent.__init__(或使用super,但如果您不熟悉它,请先阅读它,以便了解您正在做的事情)

答案 3 :(得分:1)

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

有关如何执行此操作,请参阅here

答案 4 :(得分:0)

我也遇到过这方面的问题,但我已经将super().__init__()推到了派生类的底层,这就是为什么它不起作用的原因。因为我尝试使用未初始化的属性。