inspect模塊常用功能
import inspect # 導入inspect模塊
inspect.isfunction(fn) # 檢測fn是不是函數
inspect.isgenerator((x for x in range(10))) # 檢測是否是生成器
inspect.isclass(int) # 檢測int是不是類
inspect.isbuiltin(print) # 檢測print是不是內建函數(built-in function)
import random
inspect.ismodule # 檢測random是不是模塊
我們把其中的inspect . signature(function)拿出來單獨分析,如下:
def add(x:int, y:int): # 定義一個函數
return x + y
import inspect
sig = inspect.signature(add) # 獲取一個函數的參數簽名
print(sig) # (x: int, y: int)
parms = sig.parameters
print(parms) # 打印一個有序字典,字典的key是add函數的形參,字典的values是函數的形參key對應的各種屬性,我們學習一下它的annotation屬性
# OrderedDict([('x', <Parameter "x: int">), ('y', <Parameter "y: int">)])
print(parms['x'].annotation) # <class 'int'> 形參x的注釋類型是int
應用——業務實戰
通過上面的分析,我們學到了如何獲得一個函數的注釋信息,現在我們要實現一個業務:
函數參數類型檢查,即在傳參調用的時候自動檢查傳入的實際參數和形參的注釋進行對比,如果不同,給出提示。
思路:- 函數參數的檢查,最好在函數外,可以想到使用裝飾器
- __annotation__屬性是一個字典
import inspect
from functools import wraps
def logger(fn):
d = {}
@wraps(fn)
def wrapper(*args, **kwargs):
print(kwargs)
sig = inspect.signature(fn)
params = sig.parameters
print(params)
for i,v in enumerate(params.values()):
d[f'{i}'] = v.annotation
for i,x in enumerate(args):
if d[f'{i}'] == 'inspect._empty' or type(x) == d[f'{i}']:
print(x, '很ok,沒問題')
else:
print(x, '類型不對')
for k,v in kwargs.items():
if type(v) == params[k].annotation:
print(v,'ok,可以')
else:
print(v,'不行')
ret = fn(*args, **kwargs)
# print(d)
# print(d['1'])
return ret
return wrapper
@logger
def add(x:str, y:int=7)->int:
return x + y
add(3,y='sdf')