[英]Python 3 - Decorators execution flow
The below example is taken from python cookbook 3rd edition section 9.5. 以下示例摘自python Cookbook第三版9.5节。 I placed break points at each line to understand the flow of execution .
我在每一行都放置了断点,以了解执行流程。 Below is the code sample, its output and the questions I have .
以下是代码示例,其输出和我所遇到的问题。 I have tried to explain my question , let me know if you need further info.
我试图解释我的问题,如果您需要更多信息,请告诉我。
from functools import wraps, partial
import logging
# Utility decorator to attach a function as an attribute of obj
def attach_wrapper(obj, func=None):
if func is None:
return partial(attach_wrapper, obj)
setattr(obj, func.__name__, func)
return func
def logged(level, name=None, message=None):
def decorate(func):
logname = name if name else func.__module__
log = logging.getLogger(logname)
logmsg = message if message else func.__name__
@wraps(func)
def wrapper(*args, **kwargs):
log.log(level, logmsg)
return func(*args, **kwargs)
@attach_wrapper(wrapper)
def set_message(newmsg):
nonlocal logmsg
logmsg = newmsg
return wrapper
return decorate
# Example use
@logged(logging.DEBUG)
def add(x, y):
return x + y
logging.basicConfig(level=logging.DEBUG)
add.set_message('Add called')
#add.set_level(logging.WARNING)
print (add(2, 3))
output is 输出是
DEBUG:__main__:Add called
5
I understand the concept of decorators, but this is confusing a little. 我了解装饰器的概念,但这有点令人困惑。
scenario 1 . 方案1 。 When the following line is debugged @logged(logging.DEBUG) , we get decorate = .decorate at 0x000000000< memoryaddress >>
当调试以下行@logged(logging.DEBUG)时 ,我们在0x000000000 <memoryaddress >>下获得decorate = .decorate。
Question : why would the control go back to execute the function " def decorate" ? 问题 :为什么控件会返回执行“ def decorate”功能? Is it because the "decorate" function is on the top of the stack ?
是因为“装饰”功能位于堆栈的顶部吗?
scenario 2 :When executing @attach_wrapper(wrapper) , the control goes to execute attach_wrapper(obj, func=None) and partial function returns func = 方案2 :执行@attach_wrapper(wrapper)时 ,控件转到执行attach_wrapper(obj,func = None) ,部分函数返回func =
question : why would the control go back to execute def attach_wrapper(obj, func=None): and how would this time the value for func is *.decorate..set_message at 0x000000000 > being passed to the attach_wrapper ? 问题 :为什么控件将返回执行def attach_wrapper(obj,func = None):这次将如何将func的值为* .decorate..set_message在0x000000000>传递给attach_wrapper?
This: 这个:
@logged(logging.DEBUG)
def add(x, y):
....
is the same as this: 与此相同:
def add(x, y):
....
add = logged(logging.DEBUG)(add)
Note that there are two calls there: first logged(logging.DEBUG)
returns decorate
and then decorate(add)
is called. 请注意,这里有两个调用:首先
logged(logging.DEBUG)
返回decorate
,然后调用decorate(add)
。
Same as in Scenario 1 , this: 与方案1中的相同:
@attach_wrapper(wrapper)
def set_message(newmsg):
...
is the same as this: 与此相同:
def set_message(newmsg):
...
set_message = attach_wrapper(wrapper)(set_message)
Again, there are two calls: first attach_wrapper(wrapper)
returns the partial
object and then partial(set_message)
is called. 同样,有两个调用:首先
attach_wrapper(wrapper)
返回partial
对象,然后调用partial(set_message)
。
logged
and attach_wrapper
are not decorators. logged
和attach_wrapper
不是装饰器。 Those are functions which return decorators. 这些是返回装饰器的函数。 That is why two calls are made: one to the function which returns the decorator and another the the decorator itself.
这就是为什么要进行两次调用:一个调用返回装饰器的函数,另一个调用装饰器本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.