C3 linearization
Определение#
C3-линеаризация — это алгоритм, который Python использует для построения MRO (Method Resolution Order). Он определяет строгую последовательность обхода родительских классов при поиске методов и атрибутов.
Зачем нужна#
C3 linearization была введена в Python 2.3, чтобы решить проблемы старого поиска в глубину (DFS),
который некорректно работал в сложных иерархиях. Она успешно справляется с «проблемой ромба» (diamond problem),
когда один и тот же базовый класс встречается в дереве наследования несколько раз.
Главная цель алгоритма — гарантировать монотонность: если класс A стоит перед B в списке родителей, то и во всей итоговой цепочке поиска он должен стоять раньше.
Как работает алгоритм#
Линеаризация класса L[C] вычисляется как сам класс плюс результат слияния (merge) линеаризаций его родителей и списка самих родителей.
L[C]=[C] + merge(L[P1],L[P2],…,L[Pn],[P1,P2,…,Pn])
Правила слияния (merge):
-
Берётся голова первого списка (первый элемент).
-
Если этот элемент не является «хвостом» (любым элементом, кроме первого) в других списках, он добавляется в итоговый MRO.
-
Этот элемент удаляется из всех списков, и процесс повторяется.
-
Если элемент найден в хвосте другого списка, переходим к голове следующего списка.
Пример «Ромб»
class O: pass
class A(O): pass
class B(O): pass
class C(A, B): pass
# Порядок поиска методов (MRO) для класса C:
print(C.mro())
# [C, A, B, O, object]
Ключевые мысли#
-
Алгоритм обеспечивает соблюдение локального приоритета (порядок перечисления родителей при объявлении класса сохраняется).
-
C3-линеаризация делает поведение super() предсказуемым в сложных схемах множественного наследования.
-
Если иерархия классов нарушает правила линеаризации (например, создаёт циклическое противоречие), Python выдаст ошибку TypeError: Cannot create a consistent MRO.