簡體   English   中英

Python 3-裝飾器執行流程

[英]Python 3 - Decorators execution flow

以下示例摘自python Cookbook第三版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)時 ,我們在0x000000000 <memoryaddress >>下獲得decorate = .decorate。

問題 :為什么控件會返回執行“ def decorate”功能? 是因為“裝飾”功能位於堆棧的頂部嗎?

方案2 :執行@attach_wrapper(wrapper)時 ,控件轉到執行attach_wrapper(obj,func = None) ,部分函數返回func =

問題 :為什么控件將返回執行def attach_wrapper(obj,func = None):這次將如何將func的值為* .decorate..set_message在0x000000000>傳遞給attach_wrapper?

場景1

這個:

@logged(logging.DEBUG)
def add(x, y):
    ....

與此相同:

def add(x, y):
    ....
add = logged(logging.DEBUG)(add)

請注意,這里有兩個調用:首先logged(logging.DEBUG)返回decorate ,然后調用decorate(add)

方案2

方案1中的相同:

@attach_wrapper(wrapper)
def set_message(newmsg):
    ...

與此相同:

def set_message(newmsg):
    ...
set_message = attach_wrapper(wrapper)(set_message)

同樣,有兩個調用:首先attach_wrapper(wrapper)返回partial對象,然后調用partial(set_message)


換一種說法...

loggedattach_wrapper不是裝飾器。 這些是返回裝飾器的函數。 這就是為什么要進行兩次調用:一個調用返回裝飾器的函數,另一個調用裝飾器本身。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM