python - Python 如何知道哪个参数将是装饰器中的原始函数?
问题描述
我对 Python 的更高级功能(如装饰器)不熟悉。
我无法理解 Python 解释器如何真正理解将原始函数对象放在装饰器中的位置。
让我们看一个例子:从这里获取的例子。
没有参数的简单装饰器:
def call_counter(func):
def helper(*args, **kwargs):
helper.calls += 1
return func(*args, **kwargs)
helper.calls = 0
return helper
@call_counter
def succ(x):
return x + 1
如果我们可以假设装饰器的第一个/唯一参数call_counter(func)
是需要包装的函数对象,这将非常有意义。在这种情况下succ()
功能。
但是当您谈论“带参数的装饰器”时,事情变得不一致。看下面的例子:
带有一个参数的装饰器:
def greeting(expr): # Shouldn't expr be the function here ? Or at least isn't there suppose to be another parameter.
def greeting_decorator(func): # How does Python know to pass the function down here ?
def function_wrapper(x):
print(expr + ", " + func.__name__ + " returns:")
func(x)
return function_wrapper
return greeting_decorator
@greeting("Hello")
def foo(x):
print(42)
foo("Hi")
现在我们知道 Python 没有数据类型的概念,所以函数参数没有提供关于它们将包含什么类型的对象的信息。
我对么 ?
话虽如此,让我们看一下上面示例中的行:
def greeting(expr):
如果对于装饰器,第一个参数是要包装的函数,那么该逻辑expr
应该指向foo()
正确的吗?否则应该至少有两个参数greeting()
,例如:
def greeting(func, expr):
但相反,Python 可以“神奇地”理解内部函数需要传递函数引用:
def greeting(expr):
def greeting_decorator(func): # How is it correctly put one level down ?
代码没有指定数据类型或类型信息,那么对于没有参数的装饰器,函数是如何作为第一个参数传递的,而对于有参数的装饰器,函数是如何传递给内部函数的呢?
口译员如何检测到这一点?
这里发生了什么 ?
这对我来说似乎是“魔法”。
如果我有 5 或 6 层嵌套函数会怎样?
我很确定我在这里遗漏了一些非常基本的东西。
谢谢。
解决方案
Python 计算之后的表达式@
并将结果用作装饰器函数。
Python__call__
以函数作为参数调用装饰器对象的方法。
使用
@call_counter
def succ(x):
return x + 1
callcounter
是寻找__call__
给出论点的对象func
如果你使用
@greeting("Hello")
def foo(x):
print(42)
greeting("Hello")
被评估,其结果是 Python 使用__call__
带有func
参数的方法的对象。
推荐阅读
- android - 为什么包裹的属性之一是nan?
- if-statement - 如果左侧的单元格为空,是否可以使用 arrayformula 复制上面的值?
- python - 将 pandas DataFrame 中的每小时时间序列拆分为特定日期和所有其他日期
- google-app-engine - 为什么应用引擎会忽略 app.yaml 中的 PORT 环境变量
- node.js - 如何发送 HTTP 请求以在 firebase 中发送通知?
- javascript - 将原型 B 的所有方法和属性分配给原型 A?
- javascript - How to get the first and last visible date in React Big Calendar?
- highcharts - Highstock 范围选择器按钮到 PDF 导出下拉列表
- java - 未执行字符串输入
- jquery - 存储重复对象的数量