Python中return func与return func()的区别及装饰器实例解析
装饰器中return wrapper()的行为解析
先看你代码里的核心问题:装饰器最后返回的是wrapper()而不是wrapper,这直接导致所有被装饰的函数在脚本加载阶段就被自动执行了,具体原因拆解如下:
1. Python装饰器的执行逻辑
当你用@decorator修饰一个函数时,Python会立刻执行decorator(被装饰函数),并把这个调用的返回值重新赋值给原来的函数名。比如装饰hello函数时,相当于执行了:
hello = decorator(hello)
2. wrapper和wrapper()的本质区别
wrapper:是一个未执行的函数对象,代表函数本身,只有被调用时才会执行内部代码;wrapper():是直接调用这个函数,会立刻执行wrapper函数体内的所有代码,并返回函数的执行结果(这里返回的是func()的返回值,也就是被装饰函数的返回值)。
3. 你的代码为什么自动执行所有被装饰函数
在你的装饰器里,最后返回的是wrapper(),这意味着:
- 装饰
hello函数时,decorator(hello)被调用,内部定义wrapper后,立刻执行wrapper(); wrapper()执行时,先打印Before function.,然后调用func()(也就是原来的hello()),打印hello!,再打印After function.,最后返回hello()的返回值(这里hello()没有return,所以是None);- 这个返回值会被赋值给
hello变量,此时hello已经不是原来的函数,而是wrapper()执行后的结果None; - 同理,
good_bye、thank_you、thanks_a_lot被装饰时,都会重复这个过程,所以脚本一运行,所有被装饰的函数就被依次执行了一遍。
4. 正确的装饰器写法
如果想让被装饰的函数只有在主动调用时才执行,应该返回wrapper函数对象,而不是调用它:
def decorator(func): def wrapper(): print("Before function.") val = func() print("After function.") return val return wrapper # 此处不要加括号 @decorator def hello(): print("hello!") # 此时需要主动调用hello()才会触发执行 hello()
这样装饰后,hello变量指向的是wrapper函数对象,只有当你调用hello()时,才会触发wrapper的执行,进而调用原来的hello()函数。
内容的提问来源于stack exchange,提问作者phat nhat
相关产品推荐
相关产品推荐

