Что такое self и зачем он нужен в методах класса Python
Что проверяют
Понимаете ли вы, что метод это обычная функция, а точка при вызове делает одно конкретное действие. Вопрос звучит как для начинающего, но по ответу сразу видно, знает человек объектную модель Python или заучил правило «первым параметром пишем self».
Как отвечать
self это первый позиционный параметр метода, в который при вызове через экземпляр попадает сам экземпляр. Запись obj.method(x) разворачивается в type(obj).method(obj, x): обращение к атрибуту через точку возвращает связанный метод, который уже помнит объект.
Само слово не ключевое, это соглашение. Параметр можно назвать иначе, код будет работать, но читать его никто не захочет.
class Counter:
def __init__(self, start=0):
self.value = start
def add(self, n):
self.value += n
return self.value
c = Counter()
c.add(5) # связанный метод, экземпляр подставлен
Counter.add(c, 5) # то же самое явноЗачем это сделано явно: в Python нет неявного контекста объекта, и self отделяет атрибут экземпляра от локальной переменной и от глобального имени без отдельного синтаксиса. Отсюда же следует, что self нужен только методам экземпляра: classmethod получает класс через cls, staticmethod не получает ничего и остаётся обычной функцией внутри пространства имён класса.
Сильное дополнение: сам по себе self ничего не ищет. Поиск атрибута идёт сначала по словарю экземпляра, потом по классам в порядке MRO.
Где спотыкаются
Говорят, что self обязателен в любом методе класса. У staticmethod его нет, у classmethod вместо него cls, и вызываются оба и через класс, и через экземпляр.
Путают атрибут класса и атрибут экземпляра. Присваивание в теле класса создаёт одно значение на всех, и изменяемый список или словарь внезапно оказывается общим для всех объектов. Лечится присваиванием через self в инициализаторе.
Забывают self в сигнатуре или при обращении к полю и получают либо ошибку про лишний аргумент, либо NameError, а объясняют это странностью языка. На деле это прямое следствие того, что метод обычная функция, а связывание делает протокол дескриптора.