Python - Что значит вернуть функциональный объект? - PullRequest
0 голосов
/ 17 апреля 2020

Я пытаюсь разобраться с декораторами в Python. Я получил представление о том, для чего они нужны, из различных ответов [ex] в SO: запускать код до и / или после оформленной функции без изменения самой функции. Тем не менее, у меня возникают проблемы с пониманием того, что означает возвращение объекта функции.

В чем разница между возвратом возвращаемого значения функции и возвратом функционального объекта ? Я получаю, что ссылка на саму функцию возвращается, но какая польза от этого поведения?

Я не использовал приведенный ниже синтаксис @Decorator, так как все еще изучаю его.

Например:

def some_func():
    print('returning 1')
    return 1
def Decorator(func):
    def Wrapper():
        print('doing something first')
        val = func()
        print('doing something after')
        return val
    return Wrapper
Decorated_func = Decorator(some_func)
Decorated_func()

Выполнение этого в PythonTutor: вызов Decorated_fun c () показывает, что Wrapper имеет возвращаемое значение 1, а Decorator имеет возвращаемое значение Wrapper. Означает ли это, что Decorator на самом деле имеет возвращаемое значение 1 при вызове Decorated_func()? Я бы подумал, что синтаксис этого поведения будет (в пределах Decorator) return Wrapper(). Какой смысл возвращать объект функции?

Ответы [ 3 ]

1 голос
/ 17 апреля 2020

Во-первых, давайте проясним ваш хороший, сфокусированный вопрос:

Означает ли это, что Decorator действительно возвращает значение 1, когда вызывается Decorated_fun c ()?

Нет. Decorator - это инструмент настройки. Вы кормите это функциональным объектом. Decorator вставляет этот функциональный объект в его скрытый шаблон (Wrapper), а затем возвращает настроенный Wrapper в качестве новой функции. Эта настраиваемая функция является возвращаемым значением Decorator.

Вызов, что оболочка не меняет работу Decorator. Обратите внимание, что это , а не вызов Decorator. Decorator сделал настроенную версию оболочки - , что имеет значение 1. Decorator по-прежнему сам по себе, фабрика настроек, ожидающая, когда кто-нибудь вставит какую-то другую функцию.

1 голос
/ 17 апреля 2020

Когда вы возвращаете функцию, вызывающая сторона может вызывать ее несколько раз с разными аргументами и каждый раз вычислять другой результат.

Если вы возвращаете результат вызова функции, вы просто возвращая это одно значение, оно никогда не изменится. И поскольку это не функция, вы не можете вызывать ее с другими аргументами.

Вот более простой пример:

def adder(x):
    def add_x(y):
        return x + y
    return add_x

add_1 = adder(1)
add_3 = adder(3)
print(add_1(10)) # prints 11
print(add_1(20)) # prints 21
print(add_3(10)) # prints 13

Если вы изменили его на что-то вроде return add_x(5), тогда adder(1) просто вернет 6, а не функцию, которую можно вызывать с разными аргументами.

0 голосов
/ 17 апреля 2020

Возврат функции позволяет вам «вызвать в 2 шага». Например, из одной базовой функции вы можете создать столько функций, сколько захотите.

def testDecorator(x):
    print(f'I am {x}')
    return x * 2

def printA(func):
    def wrapper(x):
       print('I am the decorator A opening')
       result = func(x)
       print('I am the decorator A ending')
       return result
    return wrapper

def printB(func):
    def wrapper(x):
       print('I am the decorator B opening')
       result = func(x)
       print('I am the decorator B ending')
       return result
    return wrapper

testA = printA(testDecorator)
testB = printB(testDecorator)
>>> testA(5)
I am the decorator A opening
I am 5
I am the decorator A ending
10
>>> testB(5)
I am the decorator B opening
I am 5
I am the decorator B ending
10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...