🐛 Типичные ошибки при повторении

⚡ Кратко

Сверяйте сообщение об ошибке с причиной и исправлением. Воспроизведите хотя бы одну ошибку самостоятельно и затем устраните её.

Ошибка 1. Создание объекта абстрактного класса

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self): pass

s = Shape()  # TypeError

Нельзя создать экземпляр класса, у которого остались нереализованные абстрактные методы. Нужно создавать объекты конкретных наследников.

Ошибка 2. Не реализовать абстрактный метод

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    # забыли area()

c = Circle(5)  # TypeError

Наследник абстрактного класса должен реализовать все абстрактные методы, иначе его тоже нельзя инстанцировать.

Ошибка 3. Забыть super().__init__() в исключении

class AgeError(Exception):
    def __init__(self, age):
        self.age = age
        # сообщение не передано в Exception

Если вы переопределяете __init__, вызовите super().__init__(...), чтобы сообщение корректно отображалось через str(e).

Ошибка 4. Наследоваться от BaseException

class MyError(BaseException):  # неправильно
    pass

Пользовательские исключения должны наследоваться от Exception или его подклассов. BaseException зарезервирован для системных исключений.

Ошибка 5. Не проверять тип в магических методах

class Vector:
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

v = Vector(1, 2)
print(v + 5)  # AttributeError

Проверяйте тип other через isinstance и возвращайте NotImplemented, если операция не поддерживается.

Ошибка 6. Некорректное сравнение в @total_ordering

@total_ordering
class Box:
    def __eq__(self, other):
        return self.size == other.size  # AttributeError, если other не Box

    def __lt__(self, other):
        return self.size < other.size

Даже с @total_ordering нужно проверять тип other и возвращать NotImplemented при несовместимых типах.

Ошибка 7. Путать __setitem__ и удаление

class MyDict:
    def __setitem__(self, key, value):
        del self._data[key]  # не то же самое, что присваивание

За присваивание отвечает __setitem__, за удаление — __delitem__.

Ошибка 8. Забыть возвращать self в инкрементном методе

class Counter:
    def __iadd__(self, other):
        self.value += other
        # нет return self

c = Counter(1)
c += 2
print(c)  # NoneType

Инкрементные методы должны изменять объект и возвращать self.