【问题标题】:Why does my decorator execute the code in this order?为什么我的装饰器按这个顺序执行代码?
【发布时间】:2019-05-28 12:46:44
【问题描述】:

我有以下代码,我很难理解为什么它会按顺序打印语句。

def main():
    print('1')
    registry=[]

def register(func):
    print('2')
    registry.append(func)
    return func

@register
def f1():
    print('3')
print('4')
f1()
main()

此代码打印:

1
2
4
3

但我想知道为什么它不打印:

1
2
3
4

@register 被调用时,我知道register(f1) 被调用,它会打印2,然后返回f1。在我看来,3 似乎应该在接下来打印,因为 f1 已返回。但是直到最后的f1() 语句才调用f1return func 不运行它返回的函数吗?

【问题讨论】:

  • 代码不会运行,因为registrymain() 函数的本地函数,并且没有在register 装饰器中定义
  • "在我看来,接下来应该打印 3,因为 f1 已返回" 但 f1 只是 返回;它被 not 调用。 (但实际上,对我来说,它会打印 2 4 3 1
  • 即使registry 是一个预定义的全局变量,输出的第一个值也会是2,因为registermain 之前运行。

标签: python python-3.x decorator


【解决方案1】:

考虑使用装饰器语法的等效代码。此外,我们将registry 设为预定义的全局变量,以便代码实际运行。

registry = []

def main():
    print('1')
    #registry=[]

def register(func):
    print('2')
    registry.append(func)
    return func

def f1():
    print('3')

f1 = register(f1)
print('4')
f1()
main()

第一个被调用的函数是register,所以输出的第一个值是2。接下来,print('4') 输出 4。第三,调用f1,输出3。最后调用main,输出1

register 从不打电话 f1;它只是将它添加到列表registry 并返回它。

【讨论】:

  • 那么如果不运行/调用函数,return func语句是做什么用的呢?
  • 它返回function 对象本身(以便它可以重新分配给原始名称);见f1 = register(f1)
  • 装饰器语法确实没有什么是你不能没有它做的;这纯粹是为了方便。
  • 基本上,像这样使用@register 可以避免在定义f1 后编写registry.append(f1)。但是通过使用装饰器,您必须确保名称 f1 实际上是指定义的函数,这就是为什么 register 也必须返回 f1
猜你喜欢
  • 2019-07-05
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 2015-07-20
  • 2021-05-10
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多