Python: inspect
import inspect def b(x, y: int = 5, *args, z, t=55, **kwargs) -> int: return x + y signature = inspect.signature(b) print(signature) print(signature.parameters) for i, (name, parameter) in enumerate(signature.parameters.items()): # name, parameter = item print(i + 1, name, parameter.annotation, parameter.kind, parameter.default) print(parameter.default is parameter.empty, end='\n' * 2)
print(x=5) 错在 x=5 是关键字传参, print函数没有定义x参数
import inspect, functools def discretion(fn): @functools.wraps(fn) def wrapper(*args, **kwargs): signature = inspect.signature(fn) parameters = signature.parameters # OrderedDict print(parameters) # OrderedDict([('x', < Parameter "x" >), ('y', < Parameter "y: int = 5" >), ('args', < Parameter "*args" >), ('z', < Parameter "z" >), ('t', < Parameter "t=55" >), ('kwargs', < Parameter "**kwargs" >)]) # for parameter in parameters.values(): # print(parameter.name,parameter.annotation,parameter.kind,parameter.default) # 找到没有显式传递的默认值参数 ******* args, kwargs 不可能有默认值 # def b(x, y: int = 5, *args, z=55, t, **kwargs): pass # 传递的默认值参数: 1. position 2. keyword only keys = tuple(parameters.keys()) default_parameters = list(keys) # 所有默认形参 print(f'keys: {keys}') print(f'args: {args}') print(f'kwargs: {kwargs}') # position arguments for i, v in enumerate(args): name = keys[i] default_parameters.remove(name) if parameters[name].annotation is inspect._empty: continue # 类型为空, 跳过检查 if isinstance(v, parameters[name].annotation): print(f'name: {name}, value: {repr(v)}, type: {parameters[name].annotation}') else: raise TypeError(f'value {repr(v)} is not type {parameters[name].annotation}') # keyword arguments for k, v in kwargs.items(): # Refactor -> Extract Method 提取公共方法 default_parameters.remove(k) if parameters[k].annotation is parameters[k].empty: continue if isinstance(v, parameters[k].annotation): print(f'name: {k}, value: {repr(v)}, type: {parameters[k].annotation}') else: raise TypeError(f'value {repr(v)} is not type {parameters[k].annotation}') # filter parameter using default if 'args' in default_parameters: default_parameters.remove('args') if 'kwargs' in default_parameters: default_parameters.remove('kwargs') for parameter in default_parameters: print(f'parameter {parameter} using default value {parameters[parameter].default}') ret = fn(*args, **kwargs) return ret return wrapper @discretion def b(x: int, y: str = '5') -> None: print(x, y) # b('5', 5) # b(4) # y有默认值, discretion没做检查 # b(4, '5') @discretion def p(x, y: int = 5, *args, z=55, t, **kwargs): print(f'x: {x}, y: {y}, args: {args}, z: {z}, t: {t}, kwargs: {kwargs}') # p(555, 22, 33, t=666) # x: 555, y: 22, args: (33,), z: 55, t: 666, kwargs: {} p(555, t=666) # keys: ('x', 'y', 'args', 'z', 't', 'kwargs') # args: (555,) # kwargs: {'t': 666}