python進階之裝飾器之2.定義一個可接受參數的裝飾器、如何定義一個屬性可由使用者修改的裝飾器、定義一個能接受選擇性參數的裝飾器

來源:互聯網
上載者:User

標籤:rate   *args   操作   裝飾器   local   icc   critical   efault   imp   

2.1.定義一個接受參數的裝飾器

前言:在理解上一篇文章的基礎上理解定義一個接受參數的裝飾器

思路:在裝飾器函數的外層再定義一個接受參數的函數,讓他返回裝飾器函數,在裝飾器函數中進行相關參數的進行操作

代碼解析如下:

from functools import wraps
import logging
# 定義外層函數logged,使用return decorate返回裝飾器函數
def logged(level, name=None, message=None):
"""
Add logging to a function. level is the logging
level, name is the logger name, and message is the
log message. If name and message aren‘t specified,
they default to the function‘s module and name.
"""
# 定義一個裝飾器,返回wrapper函數
def decorate(func):
# 對傳入的參數進行相關操作
logname = name if name else func.__module__
print(logname)
log = logging.getLogger(logname)
print(log)
logmsg = message if message else func.__name__
print(logmsg)

@wraps(func)
# 定義wrapper函數,返回被裝飾的func函數,即後面樣本中的add函數或者spam函數
def wrapper(*args, **kwargs):
log.log(level, logmsg)
return func(*args, **kwargs)
return wrapper
return decorate

# Example use
@logged(logging.DEBUG)
def add(x, y):
return x + y

print(add(2,5))

輸出:

__main__
<Logger __main__ (WARNING)>
add
7

 



@logged(logging.CRITICAL, ‘example‘)
def spam():
print(‘Spam!‘)

print(spam())
輸出:

example
<Logger example (WARNING)>
spam
Spam!

None              #若def函數後面追加一個return “hello”,則最後一個None改為hello

 

小結:

@decorator(x, y, z)def func(a, b):    pass

裝飾器處理過程跟下面的調用是等效的;

def func(a, b):    passfunc = decorator(x, y, z)(func)

2.2  如何定義一個屬性可由使用者修改的裝飾器

前言:定義一個可以傳參數的裝飾器,若現在需要給以動態修改裝飾器的屬性,改若何定義呢?

思路:此處使用訪問器函數(accessor function),然後nonlocal 來修改內部變數

代碼解析如下:

from functools import wraps, partialimport logging# Utility decorator to attach a function as an attribute of objdef attach_wrapper(obj, func=None):    if func is None:        return partial(attach_wrapper, obj)    setattr(obj, func.__name__, func)    return funcdef logged(level, name=None, message=None):    ‘‘‘    Add logging to a function. level is the logging    level, name is the logger name, and message is the    log message. If name and message aren‘t specified,    they default to the function‘s module and name.    ‘‘‘    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 setter functions        @attach_wrapper(wrapper)        def set_level(newlevel):            nonlocal level            level = newlevel        @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@logged(logging.CRITICAL, ‘example‘)def spam():    print(‘Spam!‘)# level層級預設設定為DEBUGlogging.basicConfig(level=logging.DEBUG)print(add(2, 3))# DEBUG:__main__:add# 5# Change the log messageadd.set_message(‘Add called‘)print(add(2, 3))# DEBUG:__main__:Add called# 5# Change the log leveladd.set_level(logging.WARNING)print(add(2, 3))# WARNING:__main__:Add called# 5


若使用其他對於屬性直接存取的方法,只能訪問到頂層裝飾器,例如:
@timethis@logged(logging.DEBUG)def countdown(n):    while n > 0:        n -= 1
其中頂層裝飾器函數為:@timethis,用直接存取屬性的方法會失敗,請記住這點

本小節的內容可以作為後續類裝飾器的替代
 

 

python進階之裝飾器之2.定義一個可接受參數的裝飾器、如何定義一個屬性可由使用者修改的裝飾器、定義一個能接受選擇性參數的裝飾器

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.