Приведенный ниже пример взят из 3-й редакции книги по питону, раздел 9.5.
Я поместил точки останова в каждой строке, чтобы понять ход выполнения. Ниже приведен пример кода, его вывод и вопросы, которые у меня есть. Я попытался объяснить свой вопрос, дайте мне знать, если вам нужна дополнительная информация.
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))
вывод
DEBUG:__main__:Add called
5
Я понимаю концепцию декораторов, но это немного сбивает с толку.
сценарий 1 . Когда следующая строка отлажена @ logged (logging.DEBUG) , мы получаем
decorate = .decorate в 0x000000000 <адрес памяти >>
Вопрос : почему управление возвращается к выполнению функции def decorate? Это потому, что функция decorate находится на вершине стека?
сценарий 2 : при выполнении @ attach_wrapper (обертка) управление переходит к выполнению attach_wrapper (obj, func = None) и частичная функция возвращается
func =
вопрос : почему элемент управления возвращается для выполнения def attach_wrapper (obj, func = None):
и как бы на этот раз значение для func было * .decorate..set_message в 0x000000000>
передается в attach_wrapper?