python 为什么我的子类示例不包含基类的属性(当我尝试使用它们时导致AttributeError)?

omjgkv6w  于 2023-05-05  发布在  Python
关注(0)|答案(5)|浏览(124)

我有这个基类和子类:

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示例有?

gywdnpxw

gywdnpxw1#

子类应为:

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

因为__init__被重写,所以基类的__init__代码只有在显式请求时才会运行。
尽管__init__的名字很奇怪,但它并没有被特别对待。它在对象创建后被自动调用;但除此之外,它就是一个普通的方法,并且适用普通的继承规则。

super().__init__(arguments, that, go, to, parents)

是调用方法的父版本的语法。使用*args**kwargs允许我们catch additional arguments passed to __init__pass them to the parent method;这样,当创建TypeTwoEvent时,可以为foobar指定一个值,沿着特定于基类的任何其他值。

5us2dqdw

5us2dqdw2#

您正在重写父类的构造函数(__init__)。要扩展它,需要使用super()调用显式调用父对象的构造函数。

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

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

wgxvkvu9

wgxvkvu93#

创建示例时,将调用其__init__方法。在这种情况下,它是TypeTwoEvent.__init__。超类方法将不会被自动调用,因为这会造成极大的混乱。
您应该从TypeTwoEvent.__init__调用Event.__init__(self, ...)(或者使用super,但如果您不熟悉它,请先阅读它,以便您知道您在做什么)。

f4t66c6m

f4t66c6m4#

需要从继承类的__init__方法调用基类的__init__方法。
请参阅here了解如何执行此操作。

lawou6xi

lawou6xi5#

我也遇到过同样的问题,但在我的例子中,我把super().__init__()放在了派生类的底部,这就是为什么它不起作用。因为我试图使用未初始化的属性。

相关问题