2012-04-22 127 views
14

我有以下基类和亚类:Python类继承:AttributeError的:“[子类]”对象没有属性“XXX”

class Event(object): 
    def __init__(self, sr1=None, nr1=None, foo=None, foobar=None, nr2=None, sr2=None, flag = False): 
     self.sr1 = sr1 
     self.nr1 = nr1 
     self.foo = foo 
     self.foobar = foobar 
     self.nr2 = nr2 
     self.sr2 = sr2 
     self.flag = flag 
     self.state = STATE_NON_EVENT 

    def state_name(self): 
     return STATE_NAMES[self.state] 

    def __repr__(self): 
     return '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 

    def __repr__(self): 
     return "Type Two event (Level @: {0:.2f})".format(self.sr1) 
在我的代码

此外起,我要检查的一个实例TypeTwoEvent类,检查我知道的基类中存在的字段 - 我预计它默认值为None。然而,我的代码引发以下异常:

AttributeError: 'TypeTwoEvent' object has no attribute 'foobar'

我的印象是,基类的字段将由子类和创建一个子类的实例,将实例的基类继承下(因此调用它的构造函数)...

我在这里错过了什么?为什么TypeTwoEvent不具有foobar属性 - 当派生它的基类具有foobar属性时?

+1

如下所述,您需要明确指出您还希望超类初始化。但是__ take care__:如果你有多重继承,那么做到这一点变得非常微妙。 – katrielalex 2012-04-22 14:12:55

回答

15

子类应该是:

class TypeTwoEvent(Event): 

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

    def __repr__(self): 
     return "Type Two event (Level @: {0:.2f})".format(self.sr1) 

因为你重写__init__方法,所以你需要调用父类的方法,如果你希望发生的父行为。

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

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

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

对于*args**kwargs,它只是确保我们捕捉传递给__init__所有其他参数,并将其传递给父类的方法,当你的孩子的方法签名没有做到这一点,家长需要这些参数来工作。

+0

感谢您的编辑克里斯。我是法国人,而且我经常在“它”和“它”之间混淆。不是我混淆了意思,但我学会了语言交谈,因此它((-))很容易在我脑海中交换声音。 – 2012-04-23 11:12:42

1

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

有关如何操作,请参见here

2

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

你应该叫从TypeTwoEvent.__init__Event.__init__(self, ...)(或使用super,但如果你不熟悉它,先读了它,所以你知道你在做什么)。

2

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

0

我跟这个有问题还可以,但我已经在我的派生类的底部的推杆super().__init__(),这就是为什么它不工作。因为我尝试使用未初始化的属性。

相关问题