Ответ 1
Этот Python делает то, что он делает, чтобы поддерживать динамическое добавление функций в классы.
Когда __get__
вызывается в объекте функции (обычно делается через точечный доступ .
в экземпляре класса) Python преобразует функцию в метод и неявно передает экземпляр (обычно распознаваемый как self
) как первый аргумент.
В вашем случае вы явно вызываете __get__
и явно передаете "экземпляр" 2
, который связан как первый аргумент функции x
, здесь 2
считается "экземпляром" self
>>> mul2
<bound method mul of 2>
Это приводит к методу, связанному с экземпляром 2, с одним ожидаемым аргументом, который дает умножение: вызов возвращает 2
(связанный аргумент, назначенный x
), умноженный на все, что вы указываете в качестве аргумента y
.
Обычно function()
вызывает его __call__
с соответствующими аргументами:
mul.__call__(2, 3) # 6
В качестве плюса реализация функций __get__
для функций Python предоставляется в документе Descriptor HOWTO документов Python.
Здесь вы можете увидеть преобразование с использованием types.MethodType
, которое происходит, когда вызывается __get__
:
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
return types.MethodType(self, obj, objtype)
И исходный код для заинтригованного посетителя находится в Objects/funcobject.c
.
Как вы можете видеть, не существует ли этого дескриптора, вам придется автоматически переносить функции в types.MethodType
в любое время, когда вы хотите динамически добавлять функцию в класс, что является ненужной проблемой.