|
| 1 | +## Определение |
| 2 | + |
| 3 | +!!! info "" |
| 4 | + C3-линеаризация — это алгоритм, который Python использует для построения MRO (Method Resolution Order). |
| 5 | + Он определяет строгую последовательность обхода родительских классов при поиске методов и атрибутов. |
| 6 | + |
| 7 | + |
| 8 | +## Зачем нужна |
| 9 | + |
| 10 | +<span class="badge">C3 linearization</span> была введена в Python 2.3, чтобы решить проблемы старого поиска в глубину (DFS), |
| 11 | +который некорректно работал в сложных иерархиях. Она успешно справляется с «проблемой ромба» (diamond problem), |
| 12 | +когда один и тот же базовый класс встречается в дереве наследования несколько раз. |
| 13 | +Главная цель алгоритма — гарантировать монотонность: если класс A стоит перед B в списке родителей, то и во всей итоговой цепочке поиска он должен стоять раньше. |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +## Как работает алгоритм |
| 18 | + |
| 19 | +Линеаризация класса L[C] вычисляется как сам класс плюс результат слияния (merge) линеаризаций его родителей и списка самих родителей. |
| 20 | + |
| 21 | + |
| 22 | +`L[C]`=`[C]` + `merge(L[P1],L[P2],…,L[Pn],[P1,P2,…,Pn])` |
| 23 | + |
| 24 | + |
| 25 | + |
| 26 | +Правила слияния (merge): |
| 27 | + |
| 28 | +- Берётся голова первого списка (первый элемент). |
| 29 | + |
| 30 | +- Если этот элемент не является «хвостом» (любым элементом, кроме первого) в других списках, он добавляется в итоговый MRO. |
| 31 | + |
| 32 | +- Этот элемент удаляется из всех списков, и процесс повторяется. |
| 33 | + |
| 34 | +- Если элемент найден в хвосте другого списка, переходим к голове следующего списка. |
| 35 | + |
| 36 | +Пример «Ромб» |
| 37 | + |
| 38 | +```python |
| 39 | + class O: pass |
| 40 | + class A(O): pass |
| 41 | + class B(O): pass |
| 42 | + class C(A, B): pass |
| 43 | + |
| 44 | + # Порядок поиска методов (MRO) для класса C: |
| 45 | + print(C.mro()) |
| 46 | + # [C, A, B, O, object] |
| 47 | +``` |
| 48 | +Здесь алгоритм гарантирует, что общий предок O будет проверен только после того, как будут просмотрены оба его потомка (A и B). |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +## Ключевые мысли |
| 53 | + |
| 54 | +- Алгоритм обеспечивает соблюдение локального приоритета (порядок перечисления родителей при объявлении класса сохраняется). |
| 55 | + |
| 56 | +- C3-линеаризация делает поведение super() предсказуемым в сложных схемах множественного наследования. |
| 57 | + |
| 58 | +- Если иерархия классов нарушает правила линеаризации (например, создаёт циклическое противоречие), Python выдаст ошибку TypeError: Cannot create a consistent MRO. |
| 59 | + |
| 60 | + |
| 61 | + |
0 commit comments