Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python class inheritance: AttributeError: '[SubClass]' object has no attribute 'xxx'

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?

like image 606
Homunculus Reticulli Avatar asked Apr 22 '12 14:04

Homunculus Reticulli


1 Answers

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.

like image 161
e-satis Avatar answered Oct 06 '22 07:10

e-satis