参数注释,只是注释,不会自动做类型验证

    1. def hello(name: str, age: int=20):
    2. print(f'hello {name}, your age is {age}.')
    3. hello.__annotations__
    4. # {'name': <class 'str'>, 'age': <class 'int'>}

    返回值注释

    1. def hello() -> None:
    2. print('hello world!')
    3. hello.__annotations__ # {'return': None}
    4. def square(num: int) -> int:
    5. return num * num
    6. square.__annotations__ # {'num': <class 'int'>, 'return': <class 'int'>}
    7. help(square) # square(num:int) -> int

    inspect 模块,可获取函数的参数注释和返回值注释信息

    1. import inspect
    2. sig = inspect.signature(square)
    3. sig.parameters # mappingproxy(OrderedDict([('num', <Parameter "num:int">)]))
    4. sig.return_annotation # <class 'int'>

    结合上面参数注释和 inspect 模块的用法,就可以编写一个用来检查函数参数的装饰器了

    1. import inspect
    2. import functools
    3. class ParamTypeError(Exception):
    4. pass
    5. def validate_parameters(func):
    6. @functools.wraps(func)
    7. def wrap(*args, **kwargs):
    8. sig = inspect.signature(func)
    9. for arg, param in zip(list(args) + list(kwargs.keys()), sig.parameters.values()):
    10. if param.annotation != inspect._empty:
    11. if not isinstance(arg, param.annotation):
    12. raise ParamTypeError('parameter type error', 'expect {} but got {}'.format(param.annotation, type(arg)))
    13. return func(*args, **kwargs)
    14. return wrap
    15. @validate_parameters
    16. def hello(name, age:int=20):
    17. print(f'hello {name}, age is {age}.')
    18. if __name__ == '__main__':
    19. hello('world')
    20. hello('world', age=[1, 2, 3])
    21. # __main__.ParamTypeError: ('parameter type error', "expect <class 'int'> but got <class 'str'>")