2

Within Python, I can define two classes parent and child, where the child class inherits from the parent class. Then within child I can use self and can access any methods that exist in the parent class (and presumably any other parent class in the inheritance tree) as long as the name has not been overridden in the child class.

Are there caveats to doing this? And is the recommended method just to use super()?

Code Example:

class parent:
    def add_stars(self, str):
        return '***'+str+'***'

class child(parent):
    def print_something(self):
        print(self.add_stars("Bacon"))

[In Console]
>>> c = child()
>>> c.add_stars("Wow")
'***Wow***'
>>> c.print_something()
'***Bacon***'

Edit: Going to add more clarity based on the discussion in the comments for anyone that comes across this later. What confused me was that another way of writing the above child class & getting the same functionality was to use super():

class child(parent):
    def print_something(self):
        print(super().add_stars("Bacon"))

This is the same as long as child doesn't define a method called add_stars as well. If that method does exist in child, then self will instead use the method defined in the child class, whereas super() will skip the child class and only look in superclasses. Additionally, both will use the same Method Resolution Order. What I wanted to know was, are there any issues with using self as I did in the example, when would you typically use super instead, etc?

This was answered below and in the comments.

6
  • 2
    This is the whole point of inheritance - you don't need callPrinty, a consumer of your classes can just call printy on any instance of parent or any of its children. If you need to override it in any of the children, you can. If the parent implementation also needs to be invoked, you can use super. Commented Jan 4, 2019 at 17:40
  • Hi Jon. Yep, I understand that aspect of it; tried to make that seem clear in the part of the code where I wrote c.printy() and showed the output. In the instance where a subclass needs/wants to call a parent class method as a part of another method however, it seems there are several ways to achieve this. I don't think I've seen any examples where using "self" to call a parent method is used over say super(), so I wanted to know what the drawbacks were to this approach. I might edit the post to add a more realistic requirement to the example, but didn't want to overdo it. Commented Jan 4, 2019 at 17:59
  • 2
    self.method is used where the child doesn't override that method, super().method is used when it does, but you need to explicitly bypass the override (e.g. because that's the method you're in and you don't want to cause endless recursion). I don't know what you mean by "drawbacks". Commented Jan 4, 2019 at 18:02
  • Well, for instance, if you know you're extending or accessing a method that's only defined in a specific superclass, using super over self is probably a bit more readable. Additionally super can be used to directly select which superclass method you want to access in the event of multiple-inheritance where the method name occurs more than once (assuming 'self' will just use the one that's defined first). I.e. child(p1, p2): def something(self): self.method() would use p1.method over p2.method correct? But are there any other "gotchas" / bad in practice for not using super? Commented Jan 4, 2019 at 18:11
  • "extending or accessing" are two very different cases. The point of super is that you don't have to "directly select which superclass"; if child doesn't override method then again self.method is fine. Commented Jan 4, 2019 at 18:13

2 Answers 2

2

The best way to think of super is pretend it was actually called next, as in "next in the method resolution order". In this particular case, there is no difference. Using self.some_method will try to resolve "some_method" in the current class namespace, not find it, go to the next class in the MRO, check there, find it, and it will be resolved.

If you added super, it skips the current class namespace.

In general, it is not true that the two would be equivalent. You shouldn't use super unless that is actually what you are trying to do, even in the cases where it is equivalent.

Sign up to request clarification or add additional context in comments.

Comments

0

Are there caveats to doing this?

No, your code is fine, it correctly calls the parent function.

The current code has no need of super(). If your classes had constructors, the child constructor would have to make a call to super().

PEP8 asks that you name the classes Parent and Child, with initial capital.

You would benefit from pip install flake8 and following the advice it offers when you run flake8 *.py.

Comments

Your Answer

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.