Какие типы наследования существуют в Python

Ответ

В Python, как в объектно-ориентированном языке, существует несколько типов наследования, которые позволяют создавать иерархии классов и переиспользовать код.

  1. Одиночное наследование (Single Inheritance) Класс-потомок наследует атрибуты и методы от одного родительского класса. Это самая простая и распространенная форма наследования.

    class Vehicle:
        def move(self):
            print("Moving...")
    
    class Car(Vehicle):
        pass
    
    my_car = Car()
    my_car.move()  # Вывод: Moving...
  2. Множественное наследование (Multiple Inheritance) Класс может наследоваться от нескольких родительских классов, объединяя их функциональность. Порядок родительских классов в определении важен, так как он влияет на порядок разрешения методов (MRO).

    class Engine:
        def start(self):
            print("Engine started")
    
    class Radio:
        def play_music(self):
            print("Playing music")
    
    class Car(Engine, Radio):
        pass
    
    my_car = Car()
    my_car.start()       # Вывод: Engine started
    my_car.play_music()  # Вывод: Playing music
  3. Многоуровневое наследование (Multilevel Inheritance) Создается цепочка наследования: класс C наследуется от B, который, в свою очередь, наследуется от A.

    class A:
        def method_a(self):
            print("Method A")
    
    class B(A):
        def method_b(self):
            print("Method B")
    
    class C(B):
        pass
    
    instance_c = C()
    instance_c.method_a() # Доступен из класса A
    instance_c.method_b() # Доступен из класса B
  4. Иерархическое наследование (Hierarchical Inheritance) Несколько дочерних классов наследуются от одного родительского класса.

    class Animal:
        def speak(self):
            pass
    
    class Dog(Animal):
        def speak(self):
            return "Woof!"
    
    class Cat(Animal):
        def speak(self):
            return "Meow!"

Порядок разрешения методов (MRO)

При наследовании, особенно множественном, Python использует алгоритм C3-линеаризации для определения порядка, в котором будут искаться методы в иерархии классов. Этот порядок можно посмотреть с помощью атрибута __mro__.

print(Car.__mro__)
# (<class '__main__.Car'>, <class '__main__.Engine'>, <class '__main__.Radio'>, <class 'object'>)

Ответ 18+ 🔞

Ах ты ж ёпта, ну и тема у нас сегодня! Наследование в Python, блядь. Сидишь такой, пишешь код, а тут — бац! — и нужно откуда-то методы стащить, чтобы не повторяться, как последний распиздяй. Ну, язык-то объектно-ориентированный, нехуй делать, придётся разбираться. Слушай сюда, только не усни.

Первое, что есть — одиночное наследование. Всё просто, как три копейки: один родитель, один наследник. Как в хорошей семье, блядь. Берёшь класс Vehicle, он умеет move(), и делаешь от него Car. И этот Car уже тоже умеет move(), потому что всё спизжено у папаши. Красота!

class Vehicle:
    def move(self):
        print("Moving...")

class Car(Vehicle):
    pass

my_car = Car()
my_car.move()  # Вывод: Moving...

Дальше — множественное наследование. Вот тут уже начинается цирк, ёпта. Класс может иметь несколько родителей, как какой-нибудь богатый наследник с двумя папашами-олигархами. Главное — порядок указать правильно, а то Python начнёт искать методы по своей хитрой схеме (MRO, блядь), и будет тебе пиздец, а не код.

class Engine:
    def start(self):
        print("Engine started")

class Radio:
    def play_music(self):
        print("Playing music")

class Car(Engine, Radio):
    pass

my_car = Car()
my_car.start()       # Вывод: Engine started
my_car.play_music()  # Вывод: Playing music

Теперь многоуровневое наследование. Это когда цепочка, как в матрёшке: класс C наследуется от B, а B — от A. И в итоге C тащит на себе всё дерьмо и методы от обоих предков. Удобно, но если накосячить с логикой — разбираться потом, блядь, овердохуища времени уйдёт.

class A:
    def method_a(self):
        print("Method A")

class B(A):
    def method_b(self):
        print("Method B")

class C(B):
    pass

instance_c = C()
instance_c.method_a() # Доступен из класса A
instance_c.method_b() # Доступен из класса B

Ну и иерархическое наследование. Тут один родитель плодит кучу детей, как кролик, блядь. Все они чем-то похожи, но каждый со своими приколами. Например, Animal родитель, а Dog и Cat — его отпрыски, которые переопределяют метод speak() под себя. Классика, хуле.

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

А теперь, внимание, самый сок — Порядок разрешения методов (MRO). Когда у тебя несколько родителей, Python должен решить, у кого из них брать метод, если он называется одинаково. Для этого есть алгоритм C3-линеаризации, звучит как болезнь, но на деле просто показывает порядок поиска. Посмотреть можно через __mro__, и если там каша — пиши пропало, короче.

print(Car.__mro__)
# (<class '__main__.Car'>, <class '__main__.Engine'>, <class '__main__.Radio'>, <class 'object'>)

Вот и вся магия, блядь. Главное — не нагородить таких ебуч