Python 装饰器和嵌套函数 return 语句。带括号的正确用法?
Python Decorators & Nested Functions return statement. Proper usage with parenthesis?
有什么区别 including/not 包括装饰器(和任何嵌套函数)的内部函数的 return
语句中的括号?仅当函数 returns 多于 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('my new message') 来打印我的消息,装饰。当我不使用可调用函数时,为什么这与前面的示例相比?
在装饰器中你不应该做 return inner()
这意味着您要用调用包装函数的结果替换装饰函数
您的代码将立即 打印修改后的消息,您甚至不需要尝试调用 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
您调用了 inner
函数而不是返回它。下面的代码包装了 func
函数,而不是像上面粘贴的代码那样立即调用它。
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def func():
print('Decorate this message.')
通过调用inner
函数,而不是返回函数对象,func
在修饰时被调用。
stars(func) -> inner() -> func() # with some side effects
这通常不是我们想要的。该函数被修饰为稍后调用。
更重要的是,如果您的 函数接受参数 ,这肯定行不通,因为您需要使用 valid 实际调用装饰函数将它们传递给 inner
然后再传递给 func
.
的参数
不同之处在于,有了括号,您就不会 return 装饰器函数。相反,您正在 returning 函数的 return 值,这意味着您过早地调用了装饰函数。如果没有括号,您的代码将正常工作,并且函数对象 inner
将被 returned.
总之,不要调用函数。您需要 return 实际函数本身才能使您的装饰器正常工作:
>>> 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()
时打印。
有什么区别 including/not 包括装饰器(和任何嵌套函数)的内部函数的 return
语句中的括号?仅当函数 returns 多于 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('my new message') 来打印我的消息,装饰。当我不使用可调用函数时,为什么这与前面的示例相比?
在装饰器中你不应该做 return inner()
这意味着您要用调用包装函数的结果替换装饰函数
您的代码将立即 打印修改后的消息,您甚至不需要尝试调用 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
您调用了 inner
函数而不是返回它。下面的代码包装了 func
函数,而不是像上面粘贴的代码那样立即调用它。
def stars(func):
def inner():
print("*" * 50)
func()
print("*" * 50)
return inner
@stars
def func():
print('Decorate this message.')
通过调用inner
函数,而不是返回函数对象,func
在修饰时被调用。
stars(func) -> inner() -> func() # with some side effects
这通常不是我们想要的。该函数被修饰为稍后调用。
更重要的是,如果您的 函数接受参数 ,这肯定行不通,因为您需要使用 valid 实际调用装饰函数将它们传递给 inner
然后再传递给 func
.
不同之处在于,有了括号,您就不会 return 装饰器函数。相反,您正在 returning 函数的 return 值,这意味着您过早地调用了装饰函数。如果没有括号,您的代码将正常工作,并且函数对象 inner
将被 returned.
总之,不要调用函数。您需要 return 实际函数本身才能使您的装饰器正常工作:
>>> 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()
时打印。