MakeUseOf logo

Using the super() Function in Python Classes

Woman holding a Python book in her hands
Image source: https://www.pexels.com/photo/python-book-1181671/
Princewill Inyang is an adept backend developer proficient in DevOps with vast experience in technical writing.

He holds a Bachelor of Engineering degree in Computer Engineering. Passionate about machine learning and cloud technologies, he shares insightful articles on software concepts and stays engaged with the latest trends.

When not immersed in writing or experimenting with new technologies, Princewill enjoys watching movies and drawing.
Sign in to your MakeUseOf account

Summary

  • Python's super() function allows you to call superclass methods from a subclass, making it easier to implement inheritance and method overriding.
  • The super() function is closely related to the Method Resolution Order (MRO) in Python, which determines the order in which ancestor classes are searched for methods or attributes.
  • Using super() in class constructors is a common practice to initialize common attributes in the parent class and more specific ones in the child class. Failing to use super() can lead to unintended consequences, such as missing attribute initializations.

One of the core features of Python is its OOP paradigm, which you can use to model real-world entities and their relationships.

When working with Python classes, you’ll often use inheritance and override a superclass’s attributes or methods. Python provides a super() function that lets you call the superclass’s methods from the subclass.

What Is super() and Why Do You Need It?

Using inheritance, you can make a new Python class that inherits the features of an existing class. You can also override methods of the superclass in the subclass, providing alternative implementations. However, you might want to use the new functionality in addition to the old, rather than instead of it. In this case, super() is useful.

You can use the super() function to access superclass attributes and invoke methods of the superclass. Super is essential for object-oriented programming because it makes it easier to implement inheritance and method overriding.

How Does super() Work?

Internally, super() is closely related to the Method Resolution Order (MRO) in Python, which the C3 Linearization algorithm determines.

Here's how super() works:

  1. Determine the current class and instance: When you call super() inside a method of a subclass, Python automatically figures out the current class (the class containing the method that called super()) and the instance of that class (i.e., self).
  2. Determine the superclass: super() takes two arguments—the current class and the instance—which you don't need to pass explicitly. It uses this information to determine the superclass to delegate the method call. It does this by examining the class hierarchy and the MRO.
  3. Invoke the method on the Superclass: Once it’s determined the superclass, super() allows you to call its methods as if you were calling them directly from the subclass. This enables you to extend or override methods while still using the original implementation from the superclass.

Using super() in a Class Constructor

Using super() in a class constructor is common practice, since you’ll often want to initialize common attributes in the parent class and more specific ones in the child.

To demonstrate this, define a Python class, Father, which a Son class inherits from:

class Father:
 def __init__(self, first_name, last_name):
 self.first_name = first_name
 self.last_name = last_name
class Son(Father):
 def __init__(self, first_name, last_name, age, hobby):
 # Call the parent class constructor (Father)
 super().__init__(first_name, last_name)
 self.age = age
 self.hobby = hobby
 def get_info(self):
 return f"Son's Name: {self.first_name} {self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"
# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")
# Access attributes
print(son.get_info())

Inside the Son constructor, the call to super().init() invokes the Father class constructor, passing it first_name and last_name as parameters. This ensures that the Father class can still set the name attributes correctly, even on a Son object.

[画像:using super in class constructor]
Screenshot by Princewill Inyang

If you do not call super() in a class constructor, the constructor of its parent class will not run. This can lead to unintended consequences, such as missing attribute initializations or incomplete setup of the parent class's state:

...
class Son(Father):
 def __init__(self, first_name, last_name, age, hobby):
 self.age = age
 self.hobby = hobby
...

If you now try to call the get_info method, it will raise an AttributeError because the self.first_name and self.last_name attributes have not been initialized.

[画像:trying to use parent attributes without super]
Screenshot by Princewill Inyang

Using super() in Class Methods

You can use super() in other methods, aside from constructors, in just the same way. This lets you extend or override the behavior of the superclass’s method.

class Father:
 def speak(self):
 return "Hello from Father"
class Son(Father):
 def speak(self):
 # Call the parent class's speak method using super()
 parent_greeting = super().speak()
 return f"Hello from Son\n{parent_greeting}"
# Create an instance of the Son class
son = Son()
# Call the speak method of the Son class
son_greeting = son.speak()
print(son_greeting)

The Son class inherits from the Father and has its speak method. The speak method of the Son class uses super().speak() to call the speak method of the Father class. This allows it to include the message from the parent class while extending it with a message specific to the child class.

[画像:using super in class method]
Screenshot by Princewill Inyang

Failing to use super() in a method that overrides another means the functionality present in the parent class method won’t take effect. This results in a complete replacement of the method behavior, which can lead to behavior you didn’t intend.

Understanding Method Resolution Order

Method Resolution Order (MRO) is the order in which Python searches ancestorclasses when you access a method or an attribute. MRO helps Python determine which method to call when multiple inheritance hierarchies exist.

class Nigeria():
 def culture(self):
 print("Nigeria's culture")
class Africa():
 def culture(self):
 print("Africa's culture")
class Lagos(Africa, Nigeria):
 pass
city = Lagos()
city.culture()
print(Lagos.mro())

Here's what happens when you create an instance of the Lagos class and call the culture method:

  1. Python starts by looking for the culture method in the Lagos class itself. If it finds it, it calls the method. If not, it moves on to step two.
  2. If it doesn't find the culture method in the Lagos class, Python looks at the base classes in the order they appear in the class definition. In this case, Lagos inherits first from Africa and then from Nigeria. So, Python will look for the culture method in Africa first.
  3. If it doesn't find the culture method in the Africa class, Python will then look in the Nigeria class. This behavior continues until it reaches the end of the hierarchy and throws an error if it can't find the method in any of the superclasses.
[画像:the method resolution order]
Screenshot by Princewill Inyang

The output shows the Method Resolution Order of Lagos, starting from left to right.

Common Pitfalls and Best Practices

When working with super(), there are some common pitfalls to avoid.

  1. Be mindful of the Method Resolution Order, especially in multiple inheritance scenarios. If you need to use complex multiple inheritance, you should be familiar with the C3 Linearization algorithm that Python uses to determine MRO.
  2. Avoid circular dependencies in your class hierarchy, which can lead to unpredictable behavior.
  3. Document your code clearly, especially when using super() in complex class hierarchies, to make it more understandable for other developers.

Use super() the Right Way

Python's super() function is a powerful feature when you’re working with inheritance and method overriding. Understanding how super() works and following best practices will let you create more maintainable and efficient code in your Python projects.

AltStyle によって変換されたページ (->オリジナル) /