super()

Wywołuje metodę klasy bazowej z wnętrza klasy pochodnej, najczęściej konstruktor __init__.

Zwraca
Obiekt pośredniczący, przez który wywołujesz metody następnej klasy w kolejności MRO, zwykle klasy bazowej.
Na tej stronie

Przykład

#
Python
class User:
    def __init__(self, name):
        self.name = name
        self.active = True

class Student(User):
    def __init__(self, name, world):
        super().__init__(name)
        self.world = world
        self.points = 0

ola = Student("Ola", 7)
print(ola.name, ola.active)
print(ola.world, ola.points)
Wynikzapisany wynik, możesz go sprawdzić
Ola True
7 0

Definicja i zastosowanie

#

Funkcja super() zwraca obiekt pośredniczący, przez który wywołasz metodę z klasy bazowej. Najczęściej używa się jej w __init__ klasy pochodnej: super().__init__(name) pozwala klasie bazowej ustawić swoje atrybuty, a klasa pochodna dopisuje tylko nowe.

Tak samo rozszerza się każdą nadpisaną metodę. Zamiast kopiować kod z klasy bazowej, wywołujesz super().metoda() i dokładasz coś przed albo po. Jeśli tego nie zrobisz, wersja bazowa w ogóle się nie wykona. W przypadku __init__ oznacza to brak atrybutów, które ustawia klasa bazowa.

Wewnątrz metody wystarczy napisać super() bez argumentów, bo Python sam ustali klasę i obiekt. Przy dziedziczeniu wielokrotnym super() nie wskazuje po prostu „rodzica”, tylko następną klasę w kolejności MRO obiektu. Dzięki temu każda klasa w hierarchii wykona się dokładnie raz, pod warunkiem że wszystkie konsekwentnie wywołują super().

Składnia

#
Składnia
class Pochodna(Bazowa):
    def __init__(self, a, b):
        super().__init__(a)
        self.b = b

    def metoda(self):
        wynik = super().metoda()
        ...

Parametry

#
  • type

    klasa, opcjonalna

    Klasa, za którą zaczyna się wyszukiwanie metody w kolejności MRO. Wewnątrz metod pomijana.
  • object_or_type

    obiekt lub klasa, opcjonalny

    Obiekt, dla którego wywołujesz metodę. Wewnątrz metod pomijany.

Więcej przykładów

#
Rozszerzanie nadpisanej metody
Python
class Reward:
    def __init__(self, exp):
        self.exp = exp

    def describe(self):
        return f"+{self.exp} EXP"

class StreakReward(Reward):
    def __init__(self, exp, days):
        super().__init__(exp)
        self.days = days

    def describe(self):
        return super().describe() + f" i seria {self.days} dni"

print(Reward(10).describe())
print(StreakReward(15, 7).describe())
Wynikzapisany wynik, możesz go sprawdzić
+10 EXP
+15 EXP i seria 7 dni
Bez super().__init__() brakuje atrybutów
Python
class User:
    def __init__(self, name):
        self.name = name

class Mentor(User):
    def __init__(self, name, course):
        self.course = course

darwin = Mentor("Darwin", "Python")
print(darwin.course)
print(hasattr(darwin, "name"))
Wynikzapisany wynik, możesz go sprawdzić
Python
False
super() przy dziedziczeniu wielokrotnym
Python
class Lesson:
    def start(self):
        print("Lesson: ładuję treść")

class WithTimer(Lesson):
    def start(self):
        print("WithTimer: włączam stoper")
        super().start()

class WithHints(Lesson):
    def start(self):
        print("WithHints: przygotowuję podpowiedzi")
        super().start()

class Quiz(WithTimer, WithHints):
    def start(self):
        print("Quiz: start")
        super().start()

Quiz().start()
Wynikzapisany wynik, możesz go sprawdzić
Quiz: start
WithTimer: włączam stoper
WithHints: przygotowuję podpowiedzi
Lesson: ładuję treść

super() w klasie WithTimer wywołuje metodę z WithHints, a nie z Lesson, bo tak wygląda kolejność MRO obiektu Quiz. Dzięki temu Lesson.start() wykonuje się tylko raz.

Dobre praktyki

#
  • W __init__ klasy pochodnej wywołuj super().__init__(...) na początku, zanim skorzystasz z atrybutów ustawianych przez klasę bazową.
  • Nie wpisuj nazwy klasy bazowej na sztywno, np. User.__init__(self, name). super() działa poprawnie także po zmianie hierarchii i przy dziedziczeniu wielokrotnym.
  • Przy dziedziczeniu wielokrotnym każda klasa w łańcuchu powinna wywoływać super(). Jedna klasa bez tego wywołania przerywa cały łańcuch.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.