Расширенные темы ООП
MRO (Method Resolution Order) и проблема ромбовидного наследования.
подробнее
MRO (Method Resolution Order) — порядок, в котором Python ищет методы и атрибуты в иерархии классов.
Использует алгоритм C3-линеаризации: сначала класс, затем его родительские классы слева направо, без повторов.
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
print(D.mro()) # [D, B, C, A, object]
Проблема ромбовидного наследования:
Когда класс наследуется от двух классов, имеющих общего предка, возможны дубликаты вызова методов предка.
Решение в Python: MRO гарантирует, что общий предок вызывается один раз (через super()).
class A:
def show(self):
print("A")
class B(A):
def show(self):
super().show()
print("B")
class C(A):
def show(self):
super().show()
print("C")
class D(B, C):
def show(self):
super().show()
print("D")
D().show()
# A → C → B → D (по MRO, A вызывается 1 раз)
Что такое метаклассы?
подробнее
В Python всё является объектами, включая классы. У каждого класса есть свой метакласс - класс, который создаёт этот класс.
Метакласс - это класс, который создает другие классы. Базовым метаклассом являетсяtype, от которого наследуются все другие метаклассы.
При создании класса передаются три аргумента: имя класса (
name->Class.__name__), базовые классы (bases->Class.__bases__) и словарь атрибутов (namespace->Class.__dict__). Метакласс отвечает за обработку этих данных и создание самого класса.
Для подавляющего большинства задач использование метаклассов избыточно. Часто можно обойтись декораторами классов, магическим методом
__init_subclass__или дескрипторами.
Пример:
Когда мы указываем metaclass при объявлении класса, вызывается метод __new__ указанного метакласса,
в который передаётся имя класса, кортеж его базовых классов, список его атрибутов и дополнительные именованные аргументы, указанные при объявлении класса.
# Объявляем метакласс
class MyMetaClass(type):
def __new__(mcs, name, bases, namespace):
print("Создание объекта класса")
return super().__new__(mcs, name, bases, namespace)
# Применение метакласса выглядит следующим образом
class Foo(metaclass=MyMetaClass):
pass
# Сразу после объявления класса Foo будет напечатан следующий текст
# Создание объекта класса
Метакласс может управлять процессом создания класса и:
- Изменять имя класса (
__name__) - Добавлять/удалять/модифицировать атрибуты и методы
- Изменять список базовых классов (
__bases__) - Контролировать наследование
- Валидировать определение класса
- Автоматически регистрировать классы (например, в реестре)
- Добавлять служебные атрибуты (например,
__slots__) - Изменять поведение класса до его создания
Что такое классы-миксины?
подробнее
Миксины (Mixin) - это небольшие классы, предназначенные исключительно для “подмешивания” функционала другим классам с помощью множественного наследования.
У миксинов узкая специализация. Они реализуют только одну конкретную задачу (например, логирование, сериализацию в JSON или проверку прав доступа).
Пример
class JsonMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class User(JsonMixin): # "Подмешиваем" функционал JSON
def __init__(self, name):
self.name = name
user = User("Ivan")
print(user.to_json()) # Метод пришел из миксина
Что такое сериализация и десериализация?
подробнее
Это процессы превращения данных из живых объектов программы в формат для хранения/передачи и обратно.
- Сериализация - упаковка объекта (списка, словаря, экземпляра класса) в поток байтов или строку (например, JSON), чтобы сохранить его в файл или отправить по сети.
- Десериализация - восстановление объекта из этого потока обратно в оперативную память в исходном виде.
Другими словами:
- Сериализация -
python obj->поток байтовилистрока- Десериализация -
поток байтовилистрока->python obj
Методы (модули json и pickle)
- Сериализация
dump(obj, file)- в файлdumps(obj)- в строку/байты (s = string)
- Десериализация
load(file)- читает из файлаloads(data)- Из строки/байтов (s = string)