Using super() for Parent Class Access
A base class defines shared attributes and methods; derived classes inherit from it and add their own specialized features.
Try it: Inheritance and Method Lookup
How a subclass inherits from its parent, how Python finds an attribute by walking the instance, then the class's method resolution order up to object, how overriding and super() work, why the same call does different things on different objects (polymorphism), and what isinstance / issubclass check.
How it works
- class Dog(Animal) gives Dog the MRO Dog → Animal → object; Puppy(Dog) gives Puppy → Dog → Animal → object.
- obj.name searches obj.__dict__, then each class of type(obj).__mro__ in order; the first class that defines the name wins, so a subclass method overrides the parent's.
- super().method() starts the search in the class after the one the current method was defined in, e.g. to run the parent's __init__.
- Calling the same method on a list of different objects runs each object's own version (polymorphism).
- isinstance(obj, C) is True when C is in type(obj).__mro__; if no class has the name, Python raises AttributeError.
Default run (63 steps): Ready: Animal, Dog, Cat and Puppy, then the statements you picked. Each attribute is searched along the class's MRO. … Finished. Printed: Rex the dog says Woof / Tom the cat says Meow / Bo the dog says Woof! / True / Puppy / Dog / Animal / object.
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Single inheritance only (the lab's MRO code is Python's C3 algorithm, but no class here has two parents).
Loading the simulation…
One Object, Two Layers
A derived class often needs to do two jobs when an object is created: initialize the information shared by every object in the family, and then initialize information specific to the derived class. A base class provides the shared attributes and methods. The derived class inherits those features and adds specialized ones. The purpose of super() is to let the derived class use the parent implementation instead of copying its work.
The Initialization Handoff
When a Teacher object is created, Python begins with Teacher.__init__. The derived initializer first calls the base initializer through super().__init__(name, age). Control moves to SchoolMember.__init__, which initializes the shared name and age attributes. After that call finishes, control returns to Teacher.__init__, where salary is initialized. The important order is shared initialization first, specialized initialization second.
class SchoolMember:
def __init__(self, name, age):
self.name = name
self.age = age
print("Initialized SchoolMember:", name)
class Teacher(SchoolMember):
def __init__(self, name, age, salary):
super().__init__(name, age)
self.salary = salary
print("Initialized Teacher:", name)
teacher = Teacher("Mrs. Shrividya", 40, 30000)- 1The SchoolMember initializer receives name and age and stores them on the object.
- 2The Teacher initializer receives the shared values plus salary.
- 3
super().__init__(name, age) transfers the shared initialization work to SchoolMember. - 4After the parent initializer returns, Teacher stores salary.
- 5The messages show the parent initialization completing before the derived initialization.
- SchoolMember stores the attributes shared by school members.
- Teacher inherits from SchoolMember.
super().__init__calls the inherited initializer before salary is added.- Creating the Teacher starts the initialization sequence.
Initialized SchoolMember: Mrs. Shrividya
Initialized Teacher: Mrs. ShrividyaExtending an Inherited Method
A derived class can redefine a method that already exists in the base class. This is method overriding: the derived version replaces the parent version when the method is called on an object of the derived type. The derived method can either provide completely different behavior or call the parent version first and then add specialized behavior. With super().tell(), Teacher can reuse the shared name-and-age display before adding salary, while Student can reuse the same display before adding marks.
| Method design | What happens | School example |
|---|---|---|
| Inherited unchanged | The derived object uses the base implementation | A derived class uses SchoolMember.tell without redefining it |
| Overridden | The derived class supplies its own implementation | Teacher.tell or Student.tell defines specialized output |
| Overridden and extended | The derived method calls the parent implementation and adds behavior | Teacher.tell displays shared details, then salary |
Three ways a derived class can use a method from its base class
Shared Behavior in a Loop
Teacher and Student each have the shared name and age attributes from SchoolMember, plus their own specialized attribute. Teacher has salary; Student has marks. Both also define tell(), but each version adds different information after using the common SchoolMember behavior.
Name: Mrs. Shrividya
Age: 40
Salary: 30000
Name: Asha
Age: 16
Marks: 92The loop makes the same member.tell() call for both objects. Python uses the appropriate implementation for the object: Teacher.tell() for the Teacher object and Student.tell() for the Student object. This is polymorphism. It lets code work with multiple derived classes without checking whether each object is a Teacher or a Student.
Mistakes with Parent Access
Common mistake Defining a derived __init__ method but skipping the parent initializer
What it looks likeclass Teacher(SchoolMember): def __init__(self, name, age, salary): self.salary = salaryWhy it failsThe shared initialization performed by SchoolMember.
__init__is not called, so the inherited name and age setup is omitted.Do this insteadCall super().__init__(name, age) before setting salary.Common mistake Replacing a parent method when the intention was to extend it
What it looks likedef tell(self): print("Salary:", self.salary)Why it failsThis derived implementation does not perform the shared display behavior from
SchoolMember.tell().Do this insteadCall super().tell() first, then add the salary-specific output.
Common mistake Copying shared initialization into every derived class
What it looks likeSetting name and age separately in both Teacher and Student instead of using SchoolMember.__init__.
Why it failsThe shared setup is duplicated rather than defined once in the base class.
Do this insteadKeep common attributes in the base initializer and invoke it from each derived initializer.
Common mistake Assuming every object uses exactly the base version of an overridden method
What it looks likeExpecting member.tell() to produce identical output for Teacher and Student.
Why it failsTeacher and Student define their own
tell()methods, so the same call produces type-specific behavior.Do this insteadRemember that the appropriate derived implementation runs for each object.
Put attributes and methods shared by all members in the base class. In each derived class, call the parent initializer for shared setup, then add only the attributes and behavior that make that class specialized.
Practice the Call Order
What do you think happens?
In what order will the initialization messages appear when this object is created?
Reveal answer
Initialized SchoolMember, then Initialized Teacher
Teacher.__init__ calls super().__init__ first. The SchoolMember initializer completes before Teacher continues with its own initialization.
Create a third derived class named Administrator. Give it a department attribute, initialize the shared name and age through super().__init__, and override tell() so it calls super().tell() before displaying the department.
Hints
- Make Administrator inherit from SchoolMember.
- The initializer should receive name, age, and department.
- The overridden
tell()method should callsuper().tell() before displaying department.
Tracing a Student object
A Student is created with a name, age, and marks. What does the object receive from SchoolMember, and what does Student add?
- 1Start with Student.__init__
The derived initializer receives the shared name and age values together with the Student-specific marks value.
- 2Call the parent initializer
super().__init__(name, age) sends the shared values to SchoolMember.__init__, which initializes name and age. - 3Add specialized data
Student then initializes marks on the same object.
- 4Call tell()
Student.tell()can callsuper().tell() for the shared details and then display marks.
The Student object has the inherited name and age attributes plus its own marks attribute, and its tell() method can combine shared and specialized behavior.
Key Takeaways
- 1A base class defines functionality shared by related objects, while a derived class inherits and specializes that functionality.
- 2A derived
__init__method should call the parent initializer throughsuper()so inherited attributes are initialized. - 3A derived method can override a parent method completely or call
super()to extend the parent behavior. - 4Teacher and Student can share SchoolMember functionality while adding salary and marks respectively.
- 5Polymorphism allows the same
member.tell()call to produce the appropriate behavior for each derived object.
At a glance
- Base classes hold common attributes and methods; derived classes inherit them and add specialized features.
- Use
super().__init__in a derived initializer to perform the parent class setup before derived-class setup. - Use
super().method_name() when an overridden method should preserve the parent behavior and add more behavior. - Multiple derived classes can share one base implementation while producing different results through polymorphism.