参数注释,只是注释,不会自动做类型验证
def hello(name: str, age: int=20):
print(f'hello {name}, your age is {age}.')
hello.__annotations__
# {'name': <class 'str'>, 'age': <class 'int'>}
返回值注释
def hello() -> None:
print('hello world!')
hello.__annotations__ # {'return': None}
def square(num: int) -> int:
return num * num
square.__annotations__ # {'num': <class 'int'>, 'return': <class 'int'>}
help(square) # square(num:int) -> int
inspect
模块,可获取函数的参数注释和返回值注释信息
import inspect
sig = inspect.signature(square)
sig.parameters # mappingproxy(OrderedDict([('num', <Parameter "num:int">)]))
sig.return_annotation # <class 'int'>
结合上面参数注释和 inspect
模块的用法,就可以编写一个用来检查函数参数的装饰器了
import inspect
import functools
class ParamTypeError(Exception):
pass
def validate_parameters(func):
@functools.wraps(func)
def wrap(*args, **kwargs):
sig = inspect.signature(func)
for arg, param in zip(list(args) + list(kwargs.keys()), sig.parameters.values()):
if param.annotation != inspect._empty:
if not isinstance(arg, param.annotation):
raise ParamTypeError('parameter type error', 'expect {} but got {}'.format(param.annotation, type(arg)))
return func(*args, **kwargs)
return wrap
@validate_parameters
def hello(name, age:int=20):
print(f'hello {name}, age is {age}.')
if __name__ == '__main__':
hello('world')
hello('world', age=[1, 2, 3])
# __main__.ParamTypeError: ('parameter type error', "expect <class 'int'> but got <class 'str'>")