W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你想定義一個(gè)可以接受參數(shù)的裝飾器
我們用一個(gè)例子詳細(xì)闡述下接受參數(shù)的處理過程。假設(shè)你想寫一個(gè)裝飾器,給函數(shù)添加日志功能,當(dāng)時(shí)允許用戶指定日志的級別和其他的選項(xiàng)。下面是這個(gè)裝飾器的定義和使用示例:
from functools import wraps
import logging
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.
"""
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)
return wrapper
return decorate
# Example use
@logged(logging.DEBUG)
def add(x, y):
return x + y
@logged(logging.CRITICAL, 'example')
def spam():
print('Spam!')
初看起來,這種實(shí)現(xiàn)看上去很復(fù)雜,但是核心思想很簡單。最外層的函數(shù) logged()
接受參數(shù)并將它們作用在內(nèi)部的裝飾器函數(shù)上面。內(nèi)層的函數(shù) decorate()
接受一個(gè)函數(shù)作為參數(shù),然后在函數(shù)上面放置一個(gè)包裝器。這里的關(guān)鍵點(diǎn)是包裝器是可以使用傳遞給 logged()
的參數(shù)的。
定義一個(gè)接受參數(shù)的包裝器看上去比較復(fù)雜主要是因?yàn)榈讓拥恼{(diào)用序列。特別的,如果你有下面這個(gè)代碼:
@decorator(x, y, z)
def func(a, b):
pass
裝飾器處理過程跟下面的調(diào)用是等效的;
def func(a, b):
pass
func = decorator(x, y, z)(func)
decorator(x, y, z)
的返回結(jié)果必須是一個(gè)可調(diào)用對象,它接受一個(gè)函數(shù)作為參數(shù)并包裝它,可以參考9.7小節(jié)中另外一個(gè)可接受參數(shù)的包裝器例子。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: