类型注解 (Type Hints)
Python 是一种动态类型语言,这意味着你不需要在声明变量时指定它的类型。虽然这让编码变得灵活快捷,但在大型项目中,缺乏类型信息会导致代码难以阅读和维护,IDE 能够提供的智能提示也有限。
Python 3.5 引入了类型注解 (Type Hints),允许我们(可选地)为变量、函数参数和返回值标记类型。注意,解释器不会强制验证这些类型,它们主要用于静态分析工具(如 mypy)和 IDE 的智能提示。
1. 基础语法
变量注解
age: int = 25
name: str = "Alice"
is_student: bool = True
msg: str # 仅声明类型,不赋值
函数注解
使用 -> 标记返回值类型。
def greeting(name: str) -> str:
return "Hello, " + name
def add(x: int, y: int) -> int:
return x + y
2. 容器类型 (List, Dict, Tuple)
在 Python 3.9+ 中,我们可以直接使用内置的集合类型作为泛型(Generic)。
# 整数列表
scores: list[int] = [1, 2, 3]
# 键为字符串,值为整数的字典
user_ages: dict[str, int] = {"Alice": 25, "Bob": 30}
# 包含特定类型的元组
point: tuple[int, int] = (10, 20)
from typing import List, Dict, Tuple)
3. 复杂类型:Union 和 Optional
Union (联合类型)
当一个变量可能是多种类型之一时。
# Python 3.10+ 写法
def process(data: int | str) -> None:
pass
# 旧写法 (需要导入)
from typing import Union
def process_old(data: Union[int, str]) -> None:
pass
Optional (可选类型)
当一个变量可能是某种类型,也可能是 None 时,通常用于默认参数。
# name 可以是 str 或者 None
def say_hello(name: str | None = None) -> str:
if name is None:
return "Hello, Stranger"
return f"Hello, {name}"
# 旧写法: Optional[str] 等价于 Union[str, None]
from typing import Optional
对于 name: str | None = None 的理解
初学者常会疑惑这里为什么有两个 None:
- 冒号后的
str | None是类型提示,告诉检查工具这个变量既可以是字符串,也可以是None。 - 等号后的
= None是默认值,这是 Python 的标准语法,表示如果不传参,变量默认为None。
通常这两者是配套出现的:因为有了默认值 None,所以类型提示里必须包含 None 这一项。
4. Any 类型
有时候我们确实无法确定类型,或者正在迁移旧代码,可以使用 Any。这就相当于告诉类型检查器:“这里可以是任何东西,不要检查它”。
from typing import Any
def explicit_dynamic(a: Any) -> Any:
return a.do_something()
Any,因为它会丧失类型检查的意义。
5. 自定义类型(类)
类本身就是一种类型。
class User:
def __init__(self, name: str):
self.name = name
def get_user_name(u: User) -> str:
return u.name
6. 静态类型检查工具:mypy
类型注解写了如果不检查,就只是注释而已。mypy 是 Python 官方推荐的静态类型检查工具。
安装:
pip install mypy
检查文件:
mypy script.py
如果有类型不匹配(例如把 str 传给了 int 参数),mypy 会报错。
总结
- 类型注解是可选的,不会影响代码运行。
- 使用
variable: type和-> type语法。 - Python 3.10+ 推荐使用
|代替Union。 - 类型注解能极大地提升代码可读性和 IDE 的智能提示体验。
下一步
现在我们的工具箱里已经有了各种强大的语言特性。最后,让我们快速浏览一下 Python 标准库中一些常用但还没详细介绍的模块,看看 Python 还自带了哪些“电池”。