Python Decorators & Nested Functions return statement. Proper usage with parenthesis?
有什么区别,包括/不包括装饰器内部函数(和任何嵌套函数)的
在下面的示例中,我知道除非使用
原因背后的术语会很好,所以有助于我完全理解。谢谢。
1 2 3 4 5 6 7 8 9 10 | def stars(func): def inner(): print("*" * 50) func() print("*" * 50) return inner() @stars def func(): print('Decorate this message.') |
它最初打印我的信息,装饰。但如果我再次调用func(),它将不会打印任何内容。
另一个工作示例,但是
1 2 3 4 5 6 7 8 9 10 11 | 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("我的新消息")打印我的消息,装饰一下。当我不使用可调用函数时,为什么要将其与前面的示例进行比较?
在装饰器中,不应使用
这意味着您将用调用包装的func的结果替换装饰的func。
您的代码将立即打印修改后的消息,而不必尝试调用
1 2 3 | ************************************************** Decorate this message. ************************************************** |
但当你装饰一个功能时,这并不是你想要的。
您打算修改函数的行为,但仍然需要手动调用函数。
这就是为什么代码应该是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def stars(func): def inner(): print("*" * 50) func() print("*" * 50) return inner @stars def func(): print('Decorate this message.') func() ************************************************** Decorate this message. ************************************************** |
进一步解释:
当使用decorator语法时
1 2 | @stars def func(): |
您要告诉python执行以下操作:
1 | func = stars(func) |
换言之,
如果不在代码中重用名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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. ************************************************** |
也许现在更清楚了,当我们从装饰师那里做
通过调用
1 | stars(func) -> inner() -> func() # with some side effects |
这通常不是我们想要的。函数被修饰为稍后调用。
更重要的是,在您的函数接受参数的情况下,这肯定不起作用,因为您需要实际调用带有有效参数的修饰函数,以便将它们传递给
不同的是,使用圆括号时,不会返回decorator函数。相反,您返回的是函数的返回值,这意味着您过早地调用了修饰函数。如果没有括号,代码将正常工作,并返回函数对象
简而言之,不要调用函数。您需要返回实际的函数本身,这样您的修饰器才能正常工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | >>> 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. ************************************************** >>> |
如果您无论如何调用
调用
1 2 3 4 5 6 7 8 9 10 | def stars(func): def inner(): print("*" * 50) func() print("*" * 50) return inner @stars def func(): print('Decorate this message.') |