我正在试图弄清楚装饰器在python中是如何工作的。 但是,有两件事我无法说清楚,所以如果有人帮助我理解装饰器在python中是如何工作的,我感激不尽!
这是我刚刚编写的示例代码,用于查看其工作原理。
In [22]: def deco(f):
....: def wrapper():
....: print("start")
....: f()
....: print("end")
....: return wrapper
In [23]: @deco
....: def test():
....: print("hello world")
....:
输出1
In [24]: test()
start
hello world
end
我不明白的第一件事是当我调用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
我打电话给“deco(测试)”只是为了看看它输出的结果。 如上所示,它返回“包装器”函数对象,在将其分配给变量并调用“包装器”函数后,它输出两个“开始”和一个“hello world”和两个“end”。 内部发生了什么?为什么“开始”和“结束”分别输出两次?
有人可以帮我理解这是如何运作的吗?
答案 0 :(得分:5)
我了解到当我调用test()时,它会在内部调用“deco(test)”。如果是这样,它应该返回一个“包装器”函数对象而不是输出字符串。但是,它会输出字符串作为结果。我想知道它是如何在内部完成工作的。
不完全,应用装饰器是 syntatic sugar (意味着做一些其他可能的好方法)。等效操作是
def test():
print("Hello, world!")
test = deco(test) # note that test is overwritten by the wrapper that deco returns
为了说明这一点,请考虑以下示例
>>> 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
请注意,只要定义了函数,装饰器就会应用。这符合上述“等效操作”。
在第二种情况下,当您手动将deco应用于已装饰的测试函数时,您将看到双重打印语句。