内部装饰器函数如何查看装饰函数参数? [复制]
Posted
技术标签:
【中文标题】内部装饰器函数如何查看装饰函数参数? [复制]【英文标题】:How do inner decorator functions see decorated-function arguments? [duplicate] 【发布时间】:2019-07-29 22:00:25 【问题描述】:我正在尝试征服自开始使用以来我一直避免使用的最后一个基本 Python 功能:装饰器。我没有像使用 list-comps 那样对它进行摸索,而且我不明白装饰器声明中的内部函数是如何工作的。
这是我的意思的一个例子。鉴于此块代码:
def outer(func):
def inner(*args, **kwargs):
print('Hi my name is ')
return func(*args, **kwargs)
return inner
@outer
def decorated(name):
print(name)
decorated('Bob')
我知道这会打印出来
Hi my name is
Bob
但我不明白的是inner
如何从decorated()
获得任何*args
或**kwargs
我的理解是这样的
@outer
def decorated(name):
print(name)
decorated("Bob")
相当于outer(decorated("Bob"))
。如果是这种情况,inner()
将如何访问name
参数?除了语法问题,我希望 inner 的声明看起来像 def inner(func.args, func.kwargs):
这里发生了什么?我误会了什么?
【问题讨论】:
Inner itself 被定义为一个接受*args
和**kwargs
的函数,这不是装饰器提供的东西。
所以@语法的一部分是否涉及将函数参数传递给inner
?
@outer
被调用来替换decorated
,所以decorated("Bob")
是inner('bob')
。
【参考方案1】:
我的理解是这样的
@outter def decorated(name): print(name) decorated("Bob")
相当于
outter(decorated("Bob"))
。
错了。相当于outter(decorated)("Bob")
。 decorated
被替换为outer(decorated)
的返回值(即inner
)。当您拨打decorated
时,您实际上是在拨打inner
。
您可以以交互方式检查:
>>> def outter(func):
... def inner(*args, **kwargs):
... print('Hi my name is ')
... return func(*args, **kwargs)
... return inner
...
>>> @outter
... def decorated(name):
... print(name)
...
>>> decorated
<function outter.<locals>.inner at 0x7f5aec3461e0>
【讨论】:
感谢您提供交互式检查提示。我多次解释了装饰器(和 HOF),但从未使用过交互式 Python。 @AlexYu:最佳实践是使用@functool.wraps
将名称、文档字符串和其他元数据和属性等内容复制到替换包装函数中,在这种情况下,decorated
引用几乎完全相同的repr()
输出,这就是为什么您不能在现实生活中简单地回显修饰的函数对象。一个糟糕的替代方法是回显decorated.__code__
,它只包含名称inner
,而不是完整的__qualname__
。
@MartijnPieters 我知道最佳实践。但是当我向某人解释某件事时:首先是对内部工作的解释,然后才是“最佳实践”和“为什么它们是最好的”和“它们真的是最好的”
@AlexYu:很好,但我的意思是很多人会在框架或标准库中遇到装饰器,此时 Jonas 的说明就会失败。这是您看不到太多交互式演示的原因之一。
@MartijnPieters 好的。在编写实际代码时,您是绝对正确的。但在一个人能够编写代码之前 - 他们必须被教导如何去做。这就是交互式探索很棒的地方以上是关于内部装饰器函数如何查看装饰函数参数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章