python 参数注解inspect


# 静态语言:编译过程当中会检查,会发下问题
# 动态语言:只有在运行时才会发现问题
# 1 因为编译期间不作任何检查,直到运行期间我呢提才会暴露
# 2 函数使用者并不知道参数类型的时候,容易传错参数类型

# 函数注解:给函数的形参一个类型,并有指向的return值
# python3.5开始引入
# 能够用于第三方工具(如:pycharm)提示是否有return
# 3.6能够对变量进行注解,如:i:int = 3

def add(x:int, y:int) -> int: # 声明规范是整数相加,并不强制形参类型
'''
This is add function
:param x: int
:param y: int
:return: int
'''
return x + y

print(add(4, 10))
print(add(4.0, 5.0))
print(add('abc', 'd'))

# 业务应用
# 检查实参类型
# __annotations__是一个字典,其中包括返回值类型的声明。
# inspect模块:提供回去对象信息的函数,能够检查函数和类、类型检查
# signature(callable)函数,能够获取签名(函数签名包含了一个函数的信息,包括:函数名、参数类型、函数所在的类和名称空间及其余信息)

import inspect

def add(x:int, y:int, *args, **kwargs) -> int:
'''
This is add function
:param x: int
:param y: int
:return: int
'''
return x + y

print('0 ', add.__annotations__) # 普通字典
sig = inspect.signature(add) # 拿到add函数签名((x:int, y:int, *args, **kwargs) -> int)print('---------------------')print(sig)print('1 params: ', sig.parameters) # 返回OrderedDict(有序字典)print('2 return: ', sig.return_annotation) # 返回值注解print('3 ', sig.parameters['x'])print('4 ', sig.parameters['x'].annotation) # 参数注解print('5 ', sig.parameters['args'])print('6 ', sig.parameters['args'].annotation) # 空类型 inspect._emptyprint('7 ', sig.parameters['kwargs'])print('8 ', sig.parameters['kwargs'].annotation) # 空类型 inspect._empty# inspect模块# inspect.isfunction(add) 是不是函数# inspect.ismethod(add) 是不是类的方法# inspect.isgenerator(add) 是不是生成器对象# inspect.isgeneratorfunction(add) 是不是生成器函数# inspect.isclass(add) 是不是类# inspect.ismodule(inspect) 是不是模块# inspect.isbuiltin(print) 是不是内建对象# inspect模块 - parameter对象# 保存在元组中,只读 OrderedDict([('x', <Parameter "x:int">), ('y', <Parameter "y:int">), ('args', <Parameter "*args">), ('kwargs', <Parameter "**kwargs">)])# name 参数名# annotation 参数注解,可能没有定义# default 参数缺省值,可能没有定义# empty 特殊的类,用来标记default属性或者注释annotation属性的空值# kind 实参如何绑定到形参# POSITIONAL_ONLY 值必须是位置参数提供# POSITIONAL_OR_KEYWORD 值能够做为关键字或者位置参数提供# VAR_POSITIONAL 可变位置参数,对应*args# KEYWORD_ONLY keyword_only参数,对应*或者*args以后出现的非可变关键字参数# VAR_KEYWORD 可变关键字参数,对应**kwargsdef add2(x, y:int=11, *args, z, t=10, **kwargs) -> int: return x + ysig = inspect.signature(add2)print('================================')print('1 ', sig)print('2 params ', sig.parameters)print('3 return ', sig.return_annotation)for i, item in enumerate(sig.parameters.items()): name, param = item print(i+1, name, '\n', param.annotation, '\n', param.kind, '\n', param.default) print(param.default is param.empty, end='\n\n')# 装饰器from functools import wrapsdef checker(fn): @wraps(fn) # Decorator factory def wrapper(*args, **kwargs): # 检查实参 print(args, kwargs) sig = inspect.signature(fn) params = sig.parameters # 有序字典 # 位置参数检查 param_list = tuple(params.keys()) # 转换成有序的元组 for i, v in enumerate(args): k = param_list[i] # 拿到key if isinstance(v, params[k].annotation): # 根据key拿到注解 print(v, ' is ', params[k].annotation) else: print(v, ' is not ', params[k].annotation) # 关键参数检查 for k,v in kwargs.items(): if isinstance(v, params[k].annotation): print(v, ' is ', params[k].annotation) else: errstr = '{} {} {}'.format(v, 'is not', params[k].annotation) print(errstr) raise TypeError(errstr) # 抛出异常 result = fn(*args, **kwargs) return result return wrapper@checkerdef add3(x:int, y:int=8) -> int: return x + yprint('================================')print(add3(4, y=5))add3('abc', 'bcd')print(add3(4))
相关文章
相关标签/搜索