装饰者如何运作?

crz*_*777 5 python python-decorators

我试图找出装饰器在python中是如何工作的.但是,有两件事我无法说清楚,所以如果有人帮助我理解装饰器在python中是如何工作的,我感激不尽!

这是我刚刚编写的示例代码,用于查看其工作原理.

In [22]: def deco(f):
   ....:     def wrapper():
   ....:         print("start")
   ....:         f()
   ....:         print("end")
   ....:     return wrapper

In [23]: @deco
   ....: def test():
   ....:     print("hello world")
   ....:     
Run Code Online (Sandbox Code Playgroud)

输出1

In [24]: test()
start
hello world
end
Run Code Online (Sandbox Code Playgroud)

我不明白的第一件事是当我调用test()时它输出"start","hello world","end"的原因.我了解到,当我调用test()时,它会在内部调用"deco(test)".如果是这样,它应该返回一个"包装器"函数对象而不是输出字符串.但是,它会输出字符串作为结果.我想知道它是如何在内部完成工作的.

输出2

In [28]: i = deco(test)

In [29]: i
Out[29]: <function __main__.wrapper>

In [30]: i()
start
start
hello world
end
end
Run Code Online (Sandbox Code Playgroud)

我打电话给"deco(测试)"只是为了看看它输出的结果.如上所示,它返回"包装器"函数对象,在将其分配给变量并调用"包装器"函数后,它输出两个"开始"和一个"hello world"和两个"end".内部发生了什么?为什么"开始"和"结束"分别输出两次?

有谁可以帮我理解这是如何工作的?

Pet*_*son 5

我了解到,当我调用test()时,它会在内部调用"deco(test)".如果是这样,它应该返回一个"包装器"函数对象而不是输出字符串.但是,它会输出字符串作为结果.我想知道它是如何在内部完成工作的.

不完全,应用装饰器是合成糖(意味着做一些其他可能的事情的好方法).等效操作是

def test():
    print("Hello, world!")
test = deco(test) # note that test is overwritten by the wrapper that deco returns
Run Code Online (Sandbox Code Playgroud)

为了说明这一点,请考虑以下示例

>>> def deco(f):
...     print 'applying deco' # this will print when deco is applied to test
...     def wrapper():
...             print("start")
...             f()
...             print("end")
...     return wrapper
...
>>> @deco
... def test():
...     print("Hello world!")
...
applying deco
Run Code Online (Sandbox Code Playgroud)

请注意,定义函数后立即应用装饰器.这与上述"等效操作"相匹配.

在第二种情况下,当您手动将deco应用于已装饰的测试函数时,您将看到双重打印语句.