Флейм - не флейм…
Я попытаюсь рассказать, как таки оно работает.
Когда пишем
class A(object):
def f(self):
print ‘A.f’, self
Класс A создается метаклассом type(name, bases, attrs)
>>>def f(self):
>>> print ‘A.f’, self
>>> A = type('A'), (object,), {'f':f})
<class ‘__main__’.A>
Все, что попадает в attrs - перечисленные внутри аттрибуты (функции и переменные класса). Когда type создает A, он проходит по словарю аттрибутов. Если элемент словаря - функция, то она вставляется через method дескриптор. Остальные аттрибуты не модифицируются.
Дескриптор - это специальный объект с методами __get__, __set__, __delete__. Для method descriptor достаточно __get__.
Если method дескриптор вызывается с инстанцией класса - получается bound method, с классом - unbound method
>>> a = A()
>>> a.f()
A.f <__main__.A object at 0x00D9A2D0>
>>> A.f
<unbound method A.f>
>>>
unbound method работает без сюрпризов, только всегда проверяет первый агумент на isinstance(<first argument>, A):
>>> A.f()
Traceback (most recent call last):
File “<interactive input>”, line 1, in ?
TypeError: unbound method f() must be called with A instance as first argument (got nothing instead)
>>> A.f(a)
A.f <__main__.A object at 0x00D9A2D0>
>>>
bound method немного сложнее:
>>> af = a.f
>>> af
<bound method A.f of <__main__.A object at 0x00D9A2D0>>
>>> af()
A.f <__main__.A object at 0x00D9A2D0>
Т.е. он запоминает в себе a и при вызове добавляет его как первый параметр (обычно это self)
В итоге получаем - методы по сути обычные функции, завернутые через дескрипторы, чтобы казались методами.
Помимо простоты и однозначности (def ВСЕГДА определяет свободную функцию), отсутствия необходимости в новом ключевом слове defmethod или серьезного усложнения обработки def, требующего знания о контекстах более высокого уровня (класса, модуля) мы с таким подходом еще и получаем очень гибкий механизм создания/изменения класса “на лету”.
С моей точки зрения, все вышеперечисленное вполне способно объяснить необходимость писать self. Вспомните еще про staticmethod, в котором self отсутствует, classmethod без self зато с cls - все они делаются через декораторы, создающие специализированные дескрипторы.
В соседней теме
finite state machine на Питоне я приводил пример дескриптора, который выбирает реализацию функции основываясь на внутреннем состоянии.
Ну и конечно:
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Special cases aren't special enough to break the rules.