Форум сайта python.su
Просто интересует логика рзработчиков языка..зачем каждый раз в методе класса передавать self?
Почему нет аналога this-> ?
Или может я просто не просёк всей фишки?
Поясните, пжста.
Офлайн
Возможно, “Явное лучше неявного” © ;)
Офлайн
>>> import this
Офлайн
pentoЕще один…
Просто интересует логика рзработчиков языка..зачем каждый раз в методе класса передавать self?
Почему нет аналога this-> ?
Или может я просто не просёк всей фишки?
Поясните, пжста.
Отредактировано (Июнь 7, 2007 09:00:52)
Офлайн
хорошо бы было от него избавиться
а то запись формул в функциях внутри класса получается неудобной
16e8 * self.Tres**(-2.8177) * log(self.API)**(5.7526 * log(self.Tres) - 26.9718)
и от self-а начинает рябить в глазах
Офлайн
Это уже явный флейм. Господа, желающие продолжения банкета, могут проследовать в курилку.
Офлайн
Флейм - не флейм…
Я попытаюсь рассказать, как таки оно работает.
Когда пишем
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.
Отредактировано (Июнь 7, 2007 21:26:12)
Офлайн
К цитируемому Zen of Python добавлю последнюю мантру:
Namespaces are one honking great idea – let's do more of those!
Офлайн
Здесь мелкая неточность:
с 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
Офлайн