参数注释,只是注释,不会自动做类型验证
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 * numsquare.__annotations__ # {'num': <class 'int'>, 'return': <class 'int'>}help(square) # square(num:int) -> int
inspect模块,可获取函数的参数注释和返回值注释信息
import inspectsig = inspect.signature(square)sig.parameters # mappingproxy(OrderedDict([('num', <Parameter "num:int">)]))sig.return_annotation # <class 'int'>
结合上面参数注释和 inspect 模块的用法,就可以编写一个用来检查函数参数的装饰器了
import inspectimport functoolsclass ParamTypeError(Exception):passdef 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_parametersdef 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'>")
