[TOC] >[success] # 对被装饰函数参做类型检查 >[danger] ##### 了解signature 函数 ~~~ 1.signature 获取函数中的形参个数s = signature(spam) ,参数是函数 2.s.bind_partial(int, int).arguments 获取绑定参数规定类型字典 3.s.bind(4, 5).arguments 获取实参和形参 ~~~ ~~~ from inspect import signature def spam(x, y, z=1): return x + y s = signature(spam) print(s) print(s.bind_partial(int, int).arguments) print(s.bind(4, 5)) print(s.bind(4, 5).arguments) 打印结果: (x, y, z=1) OrderedDict([('x', <class 'int'>), ('y', <class 'int'>)]) <BoundArguments (x=4, y=5)> OrderedDict([('x', 4), ('y', 5)]) ~~~ >[danger] ##### 装饰器案例 ~~~ from inspect import signature from functools import wraps # 装饰器接受参数层 用来接受数据类型 def typeassert(*ty_args, **ty_kwargs): def decorate(func): # 如果在优化模式下,禁用类型检查 if not __debug__: return func # 检查装饰函数形参个数 sig = signature(func) # 获取参数 类型和对应参数形成字典 bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments @wraps(func) def wrapper(*args, **kwargs): # 获取实参和形参 bound_values = sig.bind(*args, **kwargs) for name, value in bound_values.arguments.items(): if name in bound_types: if not isinstance(value, bound_types[name]): raise TypeError( 'Argument {} must be {}'.format(name, bound_types[name]) ) return func(*args, **kwargs) return wrapper return decorate @typeassert(int, z=int) def spam(x, y, z=42): print(x, y, z) spam("2",2) 打印结果: TypeError: Argument x must be <class 'int'> ~~~