16

I'm playing with Python Class inheritance and ran into a problem where the inherited __init__ is not being executed if called from the sub-class (code below) the result I get from Active Python is:


>>> start
Tom Sneed
Sue Ann
Traceback (most recent call last):
 File "C:\Python26\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 312, <br>in RunScript
 exec codeObject in __main__.__dict__
 File "C:\temp\classtest.py", line 22, in <module>
 print y.get_emp()
 File "C:\temp\classtest.py", line 16, in get_emp
 return self.FirstName + ' ' + 'abc'
AttributeError: Employee instance has no attribute 'FirstName'

Here's the code

class Person():
 AnotherName = 'Sue Ann'
 def __init__(self):
 self.FirstName = 'Tom'
 self.LastName = 'Sneed'
 def get_name(self):
 return self.FirstName + ' ' + self.LastName
class Employee(Person):
 def __init__(self):
 self.empnum = 'abc123'
 def get_emp(self):
 print self.AnotherName
 return self.FirstName + ' ' + 'abc'
x = Person()
y = Employee()
print 'start'
print x.get_name()
print y.get_emp()
S.Lott
393k83 gold badges520 silver badges791 bronze badges
asked May 29, 2009 at 20:28

5 Answers 5

25

Three things:

  1. You need to explicitly call the constructor. It isn't called for you automatically like in C++
  2. Use a new-style class inherited from object
  3. With a new-style class, use the super() method available

This will look like:

class Person(object):
 AnotherName = 'Sue Ann'
 def __init__(self):
 super(Person, self).__init__()
 self.FirstName = 'Tom'
 self.LastName = 'Sneed'
 def get_name(self):
 return self.FirstName + ' ' + self.LastName
class Employee(Person):
 def __init__(self):
 super(Employee, self).__init__()
 self.empnum = 'abc123'
 def get_emp(self):
 print self.AnotherName
 return self.FirstName + ' ' + 'abc'

Using super is recommended as it will also deal correctly with calling constructors only once in multiple inheritance cases (as long as each class in the inheritance graph also uses super). It's also one less place you need to change code if/when you change what a class is inherited from (for example, you factor out a base-class and change the derivation and don't need to worry about your classes calling the wrong parent constructors). Also on the MI front, you only need one super call to correctly call all the base-class constructors.

answered May 29, 2009 at 20:34
Sign up to request clarification or add additional context in comments.

5 Comments

Care must be taken when using super, please read this: fuhm.net/super-harmful
+1 for recommending new style classes, particularly as the OP's stack trace suggests they're using Python 2.6.
is there an issue if the super class does not have an init? and if so does that mean the super class can not be a 'black box'?
No issue of the superclass has no init. It's pretty black-box-ish.
Good to know about the pitfalls. I've been pretty careful so far though and all my python code calls super() all the way back up to object :)
9

You should explicitely call the superclass' init function:

class Employee(Person):
 def __init__(self):
 Person.__init__(self)
 self.empnum = "abc123"
answered May 29, 2009 at 20:32

2 Comments

That worked - but why? why would the inherited class not work the same as if you instantiated it as its own object?
Python will not automatically call the superclass' init function when instantiating a subclass. This responsability is left to the programmer. I don't know if there's a rationale behind this.
5

Employee has to explicitly invoke the parent's __init__ (not init):

 class Employee(Person): 
 def __init__(self): 
 Person.__init__(self) 
 self.empnum = 'abc123' 
answered May 29, 2009 at 20:31

Comments

2

Instead of super(class, instance) pattern why not just use super(instance) as the class is always instance.__class__?

Are there specific cases where it would not be instance.__class__?

Martijn Pieters
1.1m325 gold badges4.2k silver badges3.4k bronze badges
answered Nov 10, 2010 at 18:25

2 Comments

wow. I think it erased part of my comment. it should be "instance.__class__" of course.
This is actually an excellent question. Please watch pyvideo.org/video/879/the-art-of-subclassing (TL;DW: no, it's not instance.__class__. "self" is not neccessarily you.)
1

Using super().init() in a subclass's __init__ method calls the constructor of the parent class, ensuring proper initialization of inherited attributes and avoiding redundancy in the code.

class Employee(Person):
 def __init__(self):
 self.empnum = 'abc123'
 super().__init__()
answered Mar 11, 2024 at 7:12

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.