I am a Python novice and I am having difficulty with inheritance and using super()
The code below is giving me this error
Exception has occurred: AttributeError 'ObjB' object has no attribute 'job'
But I'm not sure why as job is an attribute of ObjB
The test code is this..
class ObjA():
def __init__(self, astr):
self.name = astr
self.decorate()
def decorate(self):
self.name = '['+self.name+']'
class ObjB(ObjA):
def __init__(self, aname, ajob):
super().__init__(aname)
self.job = ajob
def decorate(self):
super().decorate()
self.name = self.name + ' is a ' + self.job
test = ObjA('Fred')
print(test.name)
test2 = ObjB('Fred', 'Baker')
print(test2.name)
What I was expecting was this
[Fred]
[Fred] is a Baker
2 Answers 2
In your ObjB.__init__() method you are calling super().__init__(aname) before you set self.job = ajob, so that when the decorate methods are called, the self.job is not yet set. Try moving the self.job = ajob earlier in the __init__() method, like:
class ObjB(ObjA):
def __init__(self, aname, ajob):
self.job = ajob
super().__init__(aname)
Another way to fix the problem is to eliminate the decorate() methods completely:
class ObjA():
def __init__(self, astr):
self.name = '['+astr+']'
class ObjB(ObjA):
def __init__(self, aname, ajob):
super().__init__(aname)
self.job = ajob
self.name = self.name + ' is a ' + self.job
2 Comments
__init__ on ObjA to call the decorate method on ObjB. Can this be avoided?decorate() methods completely.The key thing is that when you use super in subclass to call __init__ in base class, the self passed to __init__ is the instance of subclass ObjB rather than ObjA. Therefore, the self.decorate() in ObjA's __init__ calls actually the decorate method in ObjB, that's why the job is not defined.
super().__init__ functions like this: ObjA.__init__(test2)
Below comes from Python docs about inheritance
Derived classes may override methods of their base classes. Because methods have no special privileges when calling other methods of the same object, a method of a base class that calls another method defined in the same base class may end up calling a method of a derived class that overrides it.
2 Comments
__init__ and the decorate method of ObjB to be called by ObjB's init is there a way to achieve this or do i need to restructure my class to not call the decorate method from the __init__?ObjA.decorate(self) in your __init__ method but this is a bad practice. I think you need a clear design of structure. If ObjA is meant to inherited and methods are to be overwritten, then be careful to call methods in ObjA because it may be overwritten by subclasses.Explore related questions
See similar questions with these tags.