有什么区别,包括/不包括装饰器内部函数return
语句的括号(以及任何嵌套函数)?如果函数返回多于1个变量,是否只需要括号?
在下面的示例中,我知道除非我使用return inner()
,否则这将无效,但我看到其他示例不使用()
上的return
并且它们正常工作。
背后的术语原因很棒,所以帮助我完全理解。感谢。
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner()
@stars
def func():
print('Decorate this message.')
它最初打印我的消息,装饰。但是,如果我再次调用func(),它将不会打印任何内容。
另一个工作示例,但return inner
在这种情况下工作正常,只要我设置了支持可调用变量的函数,我的示例为msg
:
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
@star
def func(msg):
print(msg)
func("Another message to be decorated")
我每次都可以打电话给func('我的新消息')来打印我的消息。当我不使用可调用函数时,为什么将此与前一个示例进行比较?
答案 0 :(得分:4)
在装饰者中,你不应该return inner()
这意味着你要用调用包装的func
的结果替换装饰的func您的代码将立即打印修改后的消息,您甚至无需致电func()
!!
**************************************************
Decorate this message.
**************************************************
但是,这不是装饰函数时的意图。
您打算修改该函数的行为,但您仍然希望必须手动调用该函数。
这就是为什么代码应该是:
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def func():
print('Decorate this message.')
func()
**************************************************
Decorate this message.
**************************************************
进一步解释:
使用装饰器语法时
@stars
def func():
你告诉python执行以下操作:
func = stars(func)
换句话说,def func
但将函数替换为调用stars(func)
的结果
如果您不在代码中重复使用名称func
,您可能会发现它不那么令人困惑。例如:
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def print_a_message():
print('Decorate this message.')
print_a_message()
**************************************************
Decorate this message.
**************************************************
现在可能更清楚的是,当我们从装饰器做return inner
时,我们告诉Python 用print_a_message
替换 inner
答案 1 :(得分:2)
通过调用inner
函数,而不是返回函数对象,在装饰时调用func
。
stars(func) -> inner() -> func() # with some side effects
这通常不是我们想要的。该函数被修饰以便稍后调用。
更多的是,在你的函数接受参数的情况下,这当然不会起作用,因为你需要实际调用带有效参数的修饰函数来让它们通过到inner
然后到func
。
答案 2 :(得分:1)
您调用inner
函数而不是返回它。下面的代码包含func
函数,而不是像您上面粘贴的代码一样立即调用它。
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def func():
print('Decorate this message.')
答案 3 :(得分:1)
不同之处在于,使用括号,您不会返回装饰器功能。而是,您返回函数的返回值,这意味着您过早地调用了修饰函数。如果没有括号,则代码将正常工作,并返回函数对象inner
。
简而言之,请勿调用此功能。您需要返回实际的函数本身,以便装饰器正常工作:
>>> def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner # Don't call inner, return it.
>>> @stars
def func():
print('Decorate this message.')
>>> func()
**************************************************
Decorate this message.
**************************************************
>>>
如果您无论如何都拨打了inner
,那么在定义func()
而不是func()
被调用时,您的信息就会被打印出来。