问题
I have the following base class and subclass:
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
Further on in my code, I am inspecting an instance of a TypeTwoEvent
class, checking for a field I know exists in the base class - I expected it to be defaulted to value None
. However, my code raises the following exception:
AttributeError: 'TypeTwoEvent' object has no attribute 'foobar'
I was under the impression that the base class fields would be inherited by the subclass and that creating an instance of a subclass will instantiate the base class (and thus invoke its constructor) ...
What am I missing here? Why does TypeTwoEvent
not have a foobar
attribute - when the base class from which it is derived has a foobar
attribute?
回答1:
Your subclass should be:
class TypeTwoEvent(Event):
def __init__(self, level=None, *args, **kwargs):
super(TypeTwoEvent, self).__init__(*args, **kwargs)
self.sr1 = level
self.state = STATE_EVENT_TWO
Because you override the __init__
method, so you need to call the parent method if you want the parent behavior to happen.
Remember, __init__
is not a special method dispite its strange name. It's just the method automatically called after the object is created. Otherwise it's an ordinary method, and ordinary inheritance rules apply.
super(ClassName, self).__init__(arguments, that, goes, to, parents)
is the syntax to call the parent version of the method.
For *args
and **kwargs
, it just ensures we catch all additional arguments passed to __init__
and pass it to the parent method, as you child method signature didn't do it and the parent need these arguments to work.
回答2:
You're overriding the constructor (__init__
) of the parent class. To extend it, you need to explicitly call the constructor of the parent with a super() call.
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
Note that the super
call is not always at the top of the __init__
method in your sub-class. Its location depends on your situation and logic.
回答3:
When the instance is created, its __init__
method is called. In this case, that is TypeTwoEvent.__init__
. Superclass methods will not be called automatically because that would be immensely confusing.
You should call Event.__init__(self, ...)
from TypeTwoEvent.__init__
(or use super
, but if you're not familiar with it, read up on it first so you know what you're doing).
回答4:
You need to call the __init__
method of the base class from the __init__
method of the inherited class.
See here for how to do this.
回答5:
I have had problem with this also, but i've putted super().__init__()
on the bottom of my derived class and that's why it doesn't work. Because i try to use attributes that is not initialized.
来源:https://stackoverflow.com/questions/10268603/python-class-inheritance-attributeerror-subclass-object-has-no-attribute