Функции реализованы как descriptors. Чтобы процитировать документацию:
В общем, дескриптор - это атрибут объекта с «поведением привязки», тот, чей доступ к атрибуту был переопределен методами в протоколе дескриптора. Этими методами являются __get__()
, __set__()
и __delete__()
. Если какой-либо из этих методов определен для объекта, он называется дескриптором.
Идея заключается в том, что метод __get__
позволяет идентифицировать как атрибут был неправдоподобным. Рассмотрим простой пример:
>>> class Descriptor(object):
... def __get__(self, obj, type=None):
... print '__get__(%r, %r)' % (obj, type)
...
>>> class A(object):
... desc = Descriptor()
...
>>> A.desc
__get__(None, <class '__main__.A'>)
>>> A().desc
__get__(<__main__.A object at 0x020F5B50>, <class '__main__.A'>)
Как вы можете видеть, и, как описано в __get__
documentation, параметр obj
позволяют отличить доступ атрибута через класс или экземпляр. Тот же механизм может использоваться внутренним Python для возврата либо связанного, либо несвязанного метода при доступе к атрибуту функции.
На практике:
>>> class A:
... def f(self):
... pass
...
>>> A.f.__get__(None, A)
<unbound method A.f>
>>> A.f.__get__(A(), A)
<bound method A.f of <__main__.A instance at 0x022082D8>>
Это все примеры 2.x Python, но, насколько я знаю, все работают одинаково для Python 3.x, за исключением того, что несвязанных методов обычные функции.
Механизм называется «дескрипторы»: http://docs.python.org/2/howto/descriptor.html. Однако это часть грубой детали реализации. – millimoose