python3: связать метод с экземпляром класса с помощью .__ get __ (), он работает, но почему? - PullRequest
7 голосов
/ 20 сентября 2011

Я знаю, что если вы хотите добавить метод к экземпляру класса, вы не можете выполнить простое присваивание, подобное этому:

>>> def print_var(self): # method to be added
        print(self.var)
>>> class MyClass:
        var = 5
>>> c = MyClass()
>>> c.print_var = print_var

это действительно приведет к тому, что print_var будет вести себя как нормальная функция,поэтому аргумент self не будет иметь своего типичного значения:

>>> c.print_var
<function print_var at 0x98e86ec>
>>> c.print_var()
Traceback (most recent call last):
  File "<pyshell#149>", line 1, in <module>
    c.print_var()
TypeError: print_var() takes exactly 1 argument (0 given)

Чтобы функция считалась методом (т. е. связывала ее с экземпляром), я использовал этот код:

>>> import types
>>> c.print_var = types.MethodType(print_var, c)
>>> c.print_var
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>>
>>> c.print_var()
5

но я обнаружил, что .__get__ также может использоваться для этой цели:

>>> c.print_var = print_var.__get__(c)
>>> c.print_var
<bound method MyClass.print_var of <__main__.MyClass object at 0x98a1bac>>
>>> c.print_var()
5

Проблема здесь в том, что это просто работает, но я не могу понять, как иЗачем.Документация о .__get__, похоже, не очень помогает.

Буду признателен, если кто-нибудь сможет прояснить такое поведение интерпретатора python.

1 Ответ

7 голосов
/ 21 сентября 2011

Информация, которую вы ищете, содержится в Руководстве по дескриптору :

Для поддержки вызовов методов функции включают метод __get__() для привязки методов во время доступа к атрибутам. Это означает, что все функции не являются дескрипторами данных, которые возвращают связанные или несвязанные методы в зависимости от того, вызваны они из объекта или класса. В чистом Python это работает так:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj)

Так что на самом деле ничего странного не происходит - метод __get__ объекта функции вызывает types.MethodType и возвращает результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...