Решение TypeError super() в Python: правильное использование
Быстрый ответ
Чтобы избежать ошибки TypeError при вызове функции super()
в Python 2.x, ваш класс должен явно наследоваться от object
:
class Parent(object): # Указываем, что Parent является потомком object
pass
class Child(Parent):
def __init__(self):
# Кто твой родитель? Правильно, Parent!
super(Child, self).__init__()
В Python 3 все классы автоматически наследуются от object
, проблема вызова функции super()
отсутствует.
Классы старого и нового стиля: за что бороться?
В Python существуют классы старого и нового стиля. В Python 2.x к старому стилю относятся классы, не наследовавшиеся от object
, и поэтому не поддерживающие super()
, а также столкнувшиеся с трудностями управления порядком разрешения методов (MRO). Как правило, они уступают во всем классам нового стиля.
Классы нового стиля, которые наследуются от object
, успешно работают с super()
, обеспечивая предсказуемый MRO. Они расширяют возможности использования, например, дескрипторов.
От старого к новому
Чтобы приспособить ваш код на Python 2.x к классам нового стиля, достаточно указать наследование вашего класса от __metaclass__ = type
. Таким образом, имеет место декларация "провозглашение благородного происхождения" уже на старте:
__metaclass__ = type # Современное решение для классов старого стиля!
class Parent: # И вот наши Parent уже во всей красе нового стиля!
pass
class Child(Parent):
def __init__(self):
# Эффект нового стиля затрагивает также и Child!
super(Child, self).__init__()
Множественное наследование: истинное происхождение
В высшем обществе Python вполне принято иметь несколько родительских классов. Но для сохранения порядка при множественном наследовании важно, чтобы все базовые классы происходили от object
:
class Base1(object):
pass
class Base2(object):
pass
class MultiDerived(Base1, Base2):
def __init__(self):
# Не забывайте уважать права всех родителей!
super(MultiDerived, self).__init__()
Неучёт этого правила может привести к неожиданной ошибке "TypeError". Лучше отказаться от подобных «сюрпризов».
Визуализация
Иерархию классов в Python можно представить как родословное древо. Взаимодействие super()
в нём будет зависеть от того, происходит ли класс от object
:
Наследование от `object` (✅) Без наследования от `object` (❌)
------------------------- ---------------------------
[👑] [🔮?]
| X
[🍏] [🍎?]
| X
[🐣] с использованием `super()` [🐥] с использованием `super()`
"Родословное древо":
- ✅ [🐣] легко обращается к методам [👑] и [🍏] используя
super()
. - ❌ В то время как [🐥] столкнулся с ошибкой
TypeError
, потому что [🔮] и [🍎] не являются классами нового стиля.
Совет: Наследуйтесь от object
, чтобы обеспечить долгое и безоблачное сосуществование с super()
!
Метакласс как волшебная палочка
__metaclass__
играет роль волшебницы, которая одним движением превращает старые классы в эффективные сущности нового стиля. Определенный на уровне модуля, он позволяет совершить переход к «новому стилю», который особенно необходим в больших проектах.
Однако, ничего не сравнится со старой доброй рефакторизацией! Поэтому по возможности подгоняйте ваши классы под новый стиль.
Секреты успешного кодового оформления
В мире Python 2.x следуйте следующим золотым правилам для бесперебойной работы:
- Все классы должны явно указывать своё наследование от
object
- Используйте
__metaclass__ = type
, чтобы просто перевести ваш большой существующий код в классы нового стиля - Все базовые классы при множественном наследовании должны наследоваться от
object
- Уделяйте регулярное внимание рефакторизации вашего кода для использования всех преимуществ классов нового стиля
Так что, оставайтесь спокойными и продолжайте писать код!
Полезные материалы
- 2. Встроенные функции — Документация Python 2.7.18 — официальная документация Python о функции
super()
. - Понимание Python super() с методами init() – Stack Overflow — практические примеры использования и объяснения работы
super()
. - super() в Python считается супер! | Глубокие мысли Рэймонда Хеттингера — вдохновляющее эссе от Рэймонда Хеттингера, ветерана сообщества Python.
- PEP 3135 – Новый Super | peps.python.org — документ, описывающий изменения функции
super()
в Python 3. - 3. Модель данных — Документация Python 2.7.18 — пошаговое описание иерархии типов в Python 2.
- Инструменты разработки классов в Python – YouTube — видеоуроки по созданию классов и использованию
super()
. - Порядок Разрешения Методов в Python 2.3 | Python.org — описание работы механизма Порядка Разрешения Методов в Python 2 для корректной работы с
super()
.