← Назад к вопросам

Как правильно пользоваться наследованием?

2.0 Middle🔥 241 комментариев
#Python Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Наследование в Python: правильный подход

Наследование — один из столпов объектно-ориентированного программирования, но его нужно использовать аккуратно. Вот ключевые принципы.

Принцип Liskov Substitution (LSP)

Подкласс должен безопасно заменять родительский класс:

class Animal:
    def make_sound(self):
        raise NotImplementedError

class Dog(Animal):
    def make_sound(self):
        return "Woof"

class Cat(Animal):
    def make_sound(self):
        return "Meow"

def play_sound(animal: Animal):
    print(animal.make_sound())

play_sound(Dog())
play_sound(Cat())

Избегай глубокой иерархии

Глубокое наследование (3+ уровней) усложняет код:

# ❌ Плохо
class Vehicle: pass
class Car(Vehicle): pass
class ElectricCar(Car): pass

# ✅ Хорошо — композиция
class Vehicle:
    def __init__(self, engine):
        self.engine = engine

class ElectricEngine:
    pass

Abstract базовые классы (ABC)

АBC гарантирует реализацию обязательных методов:

from abc import ABC, abstractmethod

class DataProcessor(ABC):
    @abstractmethod
    def process(self, data):
        pass

class JSONProcessor(DataProcessor):
    def process(self, data):
        return json.loads(data)

Композиция вместо наследования

Когда отношение "has-a" — используй композицию:

# ❌ Неправильно
class Bird:
    def fly(self): pass

class Penguin(Bird):
    def fly(self):
        raise NotImplementedError

# ✅ Правильно
class WingConfiguration(ABC):
    @abstractmethod
    def move(self): pass

class SwimmingFlippers(WingConfiguration):
    def move(self):
        return "Swimming"

class Penguin:
    def __init__(self):
        self.wings = SwimmingFlippers()

Использование super()

Используй super() для вызова методов родителя:

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

class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age

Множественное наследование

Осторожно с множественным наследованием — используй MRO:

class A:
    def method(self): return "A"

class B(A):
    def method(self): return "B"

class C(A):
    def method(self): return "C"

class D(B, C):
    pass

print(D.__mro__)

Итоговые рекомендации

  • Используй наследование для отношений "is-a", композицию для "has-a"
  • Соблюдай Liskov Substitution Principle
  • Избегай глубокой иерархии
  • Используй ABC для контрактов
  • Предпочитай композицию сложному наследованию