2013-05-30 4 views
3

Существует этот код:Доступ к функции из класса и из экземпляра этого класса

class B: 
    def f(self): 
     pass 

print(B.f) # <function B.f at 0xb711977c> 
print(B().f) # <bound method B.f of <__main__.B object at 0xb71774cc>> 

Как переводчик знает, что когда функция f доступна из объекта класса, то нормальная функция возвращается, но когда эта функция доступна из экземпляр класса, после чего возвращается метод bound? Я прочитал, что есть функция __get__, которая используется для привязки объектов с функциями, но как это работает внутри класса и класса?

+3

Механизм называется «дескрипторы»: http://docs.python.org/2/howto/descriptor.html. Однако это часть грубой детали реализации. – millimoose

ответ

1

Функции реализованы как 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, за исключением того, что несвязанных методов обычные функции.

Смежные вопросы