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