16.9. OOP Super

16.9.1. Rationale

  • Child inherits all fields and methods from parent

  • Used to avoid code duplication

  • Order is important

  • Raymond Hettinger - Super considered super! - PyCon 2015 [#Hettinger2015]_

overload

When child has method or attribute with the same name as parent. In such case child attribute will be used (will overload parent).

16.9.2. Syntax

>>> class Person:
...     def say_hello(self):
...         print('Hello Person')
>>>
>>>
>>> class Astronaut(Person):
...     def say_hello(self):
...         print('Hello Astronaut')
>>>
>>>
>>> a = Astronaut()
>>> a.say_hello()
Hello Astronaut

16.9.3. Super with Methods

>>> class Person:
...     def say_hello(self):
...         print('Hello Person')
>>>
>>>
>>> class Astronaut(Person):
...     def say_hello(self):
...         print('Hello Astronaut')
...         super().say_hello()
>>>
>>>
>>> a = Astronaut()
>>> a.say_hello()
Hello Astronaut
Hello Person
>>> class Person:
...     def say_hello(self):
...         print('Hello Person')
>>>
>>>
>>> class Astronaut(Person):
...     def say_hello(self):
...         super().say_hello()
...         print('Hello Astronaut')
>>>
>>>
>>> a = Astronaut()
>>> a.say_hello()
Hello Person
Hello Astronaut

16.9.4. Super with Attributes

Call to __init__ of super class is missed:

>>> class Person:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         self.job = 'astronaut'
>>>
>>>
>>> astro = Astronaut()
>>> print(vars(astro))
{'job': 'astronaut'}

Call super().__init__() after initialization:

>>> class Person:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
...         self.job = 'unemployed'
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         self.job = 'astronaut'
...         super().__init__()
>>>
>>>
>>> astro = Astronaut()
>>> print(vars(astro))
{'job': 'unemployed', 'firstname': 'Mark', 'lastname': 'Watney'}

Call super().__init__() before initialization:

>>> class Person:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         super().__init__()
...         self.job = 'astronaut'
>>>
>>>
>>> astro = Astronaut()
>>> print(vars(astro))
{'firstname': 'Mark', 'lastname': 'Watney', 'job': 'astronaut'}

16.9.5. Assignments

Code 16.14. Solution
"""
* Assignment: OOP Overload Super
* Required: yes
* Complexity: easy
* Lines of code: 6 lines
* Time: 5 min

English:
    1. Create class `Astronaut` which inherits from `Person`
    2. Class `Astronaut` takes two arguments `name` and `mission`
    3. Set attribute `mission` in `Astronaut` inicializer method
    4. Call initializer method of `Person` passing `name` as an argument
    5. Define method `show()` returning name and after coma - a mission name
    6. Run doctests - all must succeed

Polish:
    1. Stwórz klasę `Astronaut` dziedziczącą po `Person`
    2. Klasa `Astronaut` przyjmuje dwa argumenty `name` i `mission`
    3. Ustaw atrybut `mission` w metodzie inicjalizacyjnej w `Astronaut`
    4. Wywołaj metodę inicjalizacyjną z `Person` podając `name` jako argument
    5. Zdefiniuj metodę `show()` zwracającą imię i po przecinku - nazwę misji
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> watney = Astronaut('Watney', 'Ares 3')
    >>> watney.show()
    'Watney, Ares 3'
    >>> lewis = Astronaut('Lewis', 'Ares 3')
    >>> lewis.show()
    'Lewis, Ares 3'
"""


class Person:
    def __init__(self, name):
        self.name = name