ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Решение TypeError super() в Python: правильное использование

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы избежать ошибки TypeError при вызове функции super() в Python 2.x, ваш класс должен явно наследоваться от object:

Python
Скопировать код
class Parent(object):  # Указываем, что Parent является потомком object
    pass

class Child(Parent):
    def __init__(self):
        # Кто твой родитель? Правильно, Parent!
        super(Child, self).__init__()

В Python 3 все классы автоматически наследуются от object, проблема вызова функции super() отсутствует.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Классы старого и нового стиля: за что бороться?

В Python существуют классы старого и нового стиля. В Python 2.x к старому стилю относятся классы, не наследовавшиеся от object, и поэтому не поддерживающие super(), а также столкнувшиеся с трудностями управления порядком разрешения методов (MRO). Как правило, они уступают во всем классам нового стиля.

Классы нового стиля, которые наследуются от object, успешно работают с super(), обеспечивая предсказуемый MRO. Они расширяют возможности использования, например, дескрипторов.

От старого к новому

Чтобы приспособить ваш код на Python 2.x к классам нового стиля, достаточно указать наследование вашего класса от __metaclass__ = type. Таким образом, имеет место декларация "провозглашение благородного происхождения" уже на старте:

Python
Скопировать код
__metaclass__ = type  # Современное решение для классов старого стиля!

class Parent:  # И вот наши Parent уже во всей красе нового стиля!
    pass

class Child(Parent):
    def __init__(self):
        # Эффект нового стиля затрагивает также и Child!
        super(Child, self).__init__()

Множественное наследование: истинное происхождение

В высшем обществе Python вполне принято иметь несколько родительских классов. Но для сохранения порядка при множественном наследовании важно, чтобы все базовые классы происходили от object:

Python
Скопировать код
class Base1(object):
    pass

class Base2(object):
    pass

class MultiDerived(Base1, Base2):
    def __init__(self):
        # Не забывайте уважать права всех родителей!
        super(MultiDerived, self).__init__()

Неучёт этого правила может привести к неожиданной ошибке "TypeError". Лучше отказаться от подобных «сюрпризов».

Визуализация

Иерархию классов в Python можно представить как родословное древо. Взаимодействие super() в нём будет зависеть от того, происходит ли класс от object:

Markdown
Скопировать код
Наследование от `object` (✅)       Без наследования от `object` (❌)
-------------------------         ---------------------------
    [👑]                             [🔮?]
     |                                 X
    [🍏]                             [🍎?]
     |                                 X
  [🐣] с использованием `super()`     [🐥] с использованием `super()`

"Родословное древо":

  • [🐣] легко обращается к методам [👑] и [🍏] используя super().
  • ❌ В то время как [🐥] столкнулся с ошибкой TypeError, потому что [🔮] и [🍎] не являются классами нового стиля.

Совет: Наследуйтесь от object, чтобы обеспечить долгое и безоблачное сосуществование с super()!

Метакласс как волшебная палочка

__metaclass__ играет роль волшебницы, которая одним движением превращает старые классы в эффективные сущности нового стиля. Определенный на уровне модуля, он позволяет совершить переход к «новому стилю», который особенно необходим в больших проектах.

Однако, ничего не сравнится со старой доброй рефакторизацией! Поэтому по возможности подгоняйте ваши классы под новый стиль.

Секреты успешного кодового оформления

В мире Python 2.x следуйте следующим золотым правилам для бесперебойной работы:

  • Все классы должны явно указывать своё наследование от object
  • Используйте __metaclass__ = type, чтобы просто перевести ваш большой существующий код в классы нового стиля
  • Все базовые классы при множественном наследовании должны наследоваться от object
  • Уделяйте регулярное внимание рефакторизации вашего кода для использования всех преимуществ классов нового стиля

Так что, оставайтесь спокойными и продолжайте писать код!

Полезные материалы

  1. 2. Встроенные функции — Документация Python 2.7.18 — официальная документация Python о функции super().
  2. Понимание Python super() с методами init() – Stack Overflow — практические примеры использования и объяснения работы super().
  3. super() в Python считается супер! | Глубокие мысли Рэймонда Хеттингера — вдохновляющее эссе от Рэймонда Хеттингера, ветерана сообщества Python.
  4. PEP 3135 – Новый Super | peps.python.org — документ, описывающий изменения функции super() в Python 3.
  5. 3. Модель данных — Документация Python 2.7.18 — пошаговое описание иерархии типов в Python 2.
  6. Инструменты разработки классов в Python – YouTube — видеоуроки по созданию классов и использованию super().
  7. Порядок Разрешения Методов в Python 2.3 | Python.org — описание работы механизма Порядка Разрешения Методов в Python 2 для корректной работы с super().