需求:
實現乙個裝飾器,它用來檢查被裝飾函式的引數型別,裝飾器可以通過引數來指明函式引數型別,呼叫時如果檢測出引數不匹配則丟擲異常
@type_assert(str,int,int)
def f(a,b,c):
....
@type_assert(y=list)
def g(x,y):
....
思路:1、提取函式簽名,inspect.signature()
2、帶引數的裝飾器,也就是根據引數定製乙個裝飾器,可以看成是生產裝飾器的工廠。每次呼叫type_assert,返回乙個特定的裝飾器,然後用它去修飾其他函式
**:
import inspect
# 帶引數的裝飾器,製造工廠的工廠
def type_assert(*ty_args,**ty_kwargs):
def decorator(func):
# a...
func_sig = inspect.signature(func)
bind_type = func_sig.bind_partial(*ty_args,**ty_kwargs).arguments
def wrap(*args,**kwargs):
# b...
for name,obj in func_sig.bind(*args,**kwargs).arguments.items():
type_ = bind_type.get(name)
if type_:
if not isinstance(obj,type_):
raise typeerror('%s must be %s' % (name,type_))
return func(*args,**kwargs)
return wrap
return decorator
@type_assert(c=str)
def f(a,b,c):
pass
>>> def f(a,b,c):
... pass
...
... f_sig = inspect.signature(f)
>>> f_sig.parameters
>>> pa = f_sig.parameters['a']
>>> pa.name
'a'>>> pa.kind
<_parameterkind.positional_or_keyword: 1>
>>> pa.default
>>> ba = f_sig.bind(int,int,str)
>>> ba.arguments
ordereddict([('a', ), ('b', ), ('c', )])
>>> ba.arguments['a']
>>> f_sig.bind(str,list)
traceback (most recent call last):
file "", line 1, in f_sig.bind(str,list)
file "/home/richardo/anaconda3/lib/python3.7/inspect.py", line 3002, in bind
return args[0]._bind(args[1:], kwargs)
file "/home/richardo/anaconda3/lib/python3.7/inspect.py", line 2917, in _bind
raise typeerror(msg) from none
typeerror: missing a required argument: 'c'
>>> f_sig.bind_partial(str,list)
, b=)>
>>>
Python 如何定義帶引數的裝飾器?
案例 實現乙個裝飾器,用它來檢查被裝飾函式的引數型別。需求 裝飾器可以通過函式,指明函式引數型別,進行函式呼叫的時候,傳入引數,檢測到不匹配時,丟擲異常 如何解決這個問題?先要獲取函式的簽名,並且獲得裝飾器中引數,然後把函式簽名和裝飾器中引數對應繫結 把呼叫函式時候傳入的引數和函式簽名進行繫結 把實...
python如何定義帶引數的裝飾器
案例 實現乙個裝飾器,用它來檢查被裝飾函式的引數型別。需求 裝飾器可以通過程式設計客棧函式,指明函式引數型別,進行函式呼叫的時候,傳入引數,檢測到不匹配時,丟擲異常 如何解決這個問題?先要獲取函式的簽名,並且獲得裝飾器中引數,然後把函式簽名和裝飾器中引數對應繫結 把呼叫函式時候傳入的引數和函式簽名進...
裝飾器帶引數
裝飾器帶引數 帶引數的裝飾器是三層的 最外層的函式負責接受裝飾器引數 裡面的內容還是源裝飾器的內容 def outer a 第一層 負責接受引數的 defdecorate func 第二層 負責接受函式的 def wargs,kwargs 第三層 負責接受函式的引數 func wargs print...