问题的历史
函数注解出现在Python 3.0中,类型提示机制(type hints)在PEP 484中描述,并在3.5中添加。该工具旨在进行代码的静态分析、自动补全和提高可读性——类型标准库(typing)允许明确指定变量、参数和函数返回值的预期类型。
问题
Python是一种动态语言,变量的类型在执行期间可以改变,这可能导致在程序执行阶段才出现错误。注解不会影响代码的执行,但不当使用时会使程序员产生"严格类型检查"的错误感觉。
解决方案
类型注解用于文档、通过mypy、pylance、pyright等工具进行自动检查,以及与IDE的集成。通过参数名称后的冒号和参数列表后的箭头实现:**
def greet(name: str, times: int = 1) -> None: for _ in range(times): print(f"Hello, {name}!") # 处理字典的正确注解 from typing import Dict, List def transform(data: Dict[str, List[int]]) -> float: return sum(sum(lst) for lst in data.values()) / 10
关键特性:
Python可以"自动"检查注解中声明的类型吗?
不!类型检查仅通过外部静态分析工具进行,例如mypy。在运行时,Python完全忽略注解的内容。
def f(x: int): return x * 2 print(f('oops')) # 类型str,不会出错!
注解存储在哪里,如何在运行时获取,为什么这可能是必要的?
存储在特殊属性__annotations__中:
def add(x: int, y: int) -> int: return x + y print(add.__annotations__) # {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
第三方库可以使用这些进行数据验证、文档自动生成、序列化等。
可以注解任何变量吗,仅限函数,全球范围内会怎样?
可以通过冒号注解本地和全局变量,这也不会影响执行:
index: int = 0 def func(x: 'User') -> None: ...
在一个企业项目中,所有开发人员开始积极采用注解,但实际函数参数的类型常常与指定类型不符。Python忽略了这些错误,意外的bug只在业务逻辑的深处出现。没有配置mypy。
优点:
缺点:
在CI中强制使用类型提示和mypy,还通过__annotations__自动生成文档:
优点:
缺点: