Как работают дескрипторы функций?

Я читал презентацию на объектной модели Pythons, когда на одном слайде (номер 9) автор утверждает, что Pythons '- дескрипторы. Пример, который он представляет для иллюстрации, похож на тот, который я написал:

def mul(x, y):
    return x * y

mul2 = mul.__get__(2)
mul2(3) # 6

Теперь я понимаю, что точка создана, поскольку функция определяет __get__, это дескриптор, как я описал в разделе описания документации Python.

То, что я не понимаю, - это то, как точно результат выводится на выходе.

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