Найти - Пользователи
Полная версия: В чём тайный смысл в передаче методу класса self?
Начало » Python для экспертов » В чём тайный смысл в передаче методу класса self?
1 2
pento
Просто интересует логика рзработчиков языка..зачем каждый раз в методе класса передавать self?
Почему нет аналога this-> ?
Или может я просто не просёк всей фишки?
Поясните, пжста.
Maximbo
Возможно, “Явное лучше неявного” © ;)
tabajara
>>> import this
bialix
pento
Просто интересует логика рзработчиков языка..зачем каждый раз в методе класса передавать self?
Почему нет аналога this-> ?
Или может я просто не просёк всей фишки?
Поясните, пжста.
Еще один…
Читайте про пространства имен в питоне. Потом подумайте еще раз над своим вопросом.
Это не фишка – это дизайн языка.
asv13
хорошо бы было от него избавиться
а то запись формул в функциях внутри класса получается неудобной
16e8 * self.Tres**(-2.8177) * log(self.API)**(5.7526 * log(self.Tres) - 26.9718)
и от self-а начинает рябить в глазах
Maximbo
Это уже явный флейм. Господа, желающие продолжения банкета, могут проследовать в курилку.
Андрей Светлов
Флейм - не флейм…
Я попытаюсь рассказать, как таки оно работает.

Когда пишем
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.
bialix
К цитируемому Zen of Python добавлю последнюю мантру:

Namespaces are one honking great idea – let's do more of those!
bialix
Здесь мелкая неточность:

с bound method все немного сложнее:
>>> af = a.f()
>>> af
<bound method A.f of <__main__.A object at 0x00D9A2D0>>

Должно быть

>>> af = a.f
Андрей Светлов
bialix
Здесь мелкая неточность:

с bound method все немного сложнее:
>>> af = a.f()
>>> af
<bound method A.f of <__main__.A object at 0x00D9A2D0>>

Должно быть

>>> af = a.f
поправил
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB