Python-返回函数对象是什么意思?

时间:2020-04-16 22:31:46

标签: python oop decorator

我正在努力让Python的Decorators成为现实。我从SO的各种答案 [ex]中了解了它们的用途:在修饰函数之前和/或之后运行代码,而无需修改函数本身。也就是说,我很难理解返回函数对象的含义。

返回函数的返回值和返回函数对象有什么区别?我知道返回了对函数本身的引用,但是此行为的用途是什么?

由于我仍在学习中,因此未使用下面的@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_func()显示Wrapper的返回值为1,而Decorator的返回值为Wrapper。这是否意味着在调用Decorator1实际上 的返回值为Decorated_func()?我以为该行为的语法将是(在Decorator之内return Wrapper()。返回功能对象有什么意义?

3 个答案:

答案 0 :(得分:1)

返回函数时,调用者可以使用不同的参数多次调用它,并且每次可以计算出不同的结果。

如果返回调用函数的结果,则仅返回该值,它将永远不会改变。而且由于它不是一个函数,所以不能使用其他参数来调用它。

这是一个更简单的示例:

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,而不是可以使用不同参数调用的函数。

答案 1 :(得分:1)

首先,让我们澄清您的重点问题:

这是否意味着在调用Decorated_func()时,装饰器实际上的返回值为1?

不。 Decorator是配置工具。您向它提供一个函数对象。 Decorator将该函数对象插入其隐藏模板(Wrapper)中,然后将自定义的Wrapper作为新函数返回。该自定义函数是Decorator的返回值。

调用包装程序并不会改变Decorator的工作方式。请注意,这不是对Decorator的调用。 Decorator制作了包装的自定义版本- 1的值。 Decorator仍然是它的原始自我,一个定制工厂,正在等待某人插入其他功能。

答案 2 :(得分:0)

返回功能可让您“分两步调用”。例如,您可以从同一基本函数创建所需数量的函数。

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