Python 的类型标注(Type Hints) 是 Python 3.5+ 引入的语法,核心作用是给变量、函数参数 / 返回值标注 "预期类型" ------ 它不影响代码运行(Python 仍是动态类型语言),但能让开发者、编辑器(如 VS Code/PyCharm)和静态检查工具(如 mypy)明确代码的类型逻辑,大幅提升可读性和可维护性。
一、为什么要用?
- 代码自文档化:一眼看懂变量 / 函数的类型意图(比如 age: int 明确是整数,不用看注释);
- 编辑器智能提示:补全属性、提示类型错误(比如给 int 类型变量调用 split() 会直接标红);
- 提前发现 bug:静态检查工具(mypy)能在运行前找出类型不匹配的问题(比如传字符串给需要整数的参数);
- 团队协作友好:避免因 "猜类型" 导致的错误,尤其适合大型项目/自定义库开发。
二、变量标注
1、基本写法
用 "变量名:类型 = 值" 的格式,: 是类型标注的分隔符,右边是预期类型。
python
# 基础类型标注
age: int = 25 # 整数
name: str = "张三" # 字符串
is_valid: bool = True # 布尔值
score: float = 98.5 # 浮点数
# 容器类型(Python 3.9+ 推荐小写,3.8- 需从 typing 导入大写)
nums: list[int] = [1, 2, 3] # 整数列表
person: dict[str, str] = {"name": "张三", "city": "北京"} # 字符串键值对字典
coords: tuple[int, float] = (10, 20.5) # 固定长度的元组(第1个int,第2个float)
2、可选类型(允许为 None)
用 "Optional[类型]"(3.8-)或 "类型 | None"(3.10+)标注 "变量可以是指定类型,也可以是 None":
python
# Python 3.8- 需导入 Optional
from typing import Optional
connection: Optional[str] = None # 可以是字符串,也可以是 None
# Python 3.10+ 更简洁(无需导入)
connection: str | None = None
3、前向引用(标注未定义的类)
如果标注的类型是尚未定义的类,用字符串包裹类名(或导入 from future import annotations):
python
# 写法1:字符串前向引用(兼容所有版本)
all_contacts: list["Contact"] = []
# 写法2:导入 annotations(3.7+),无需引号
from __future__ import annotations
all_contacts: list[Contact] = []
# 后续定义 Contact 类
class Contact:
name: str
phone: str
三、函数标注
1、基本写法
用 "def 函数名(参数名: 类型, ...) -> 返回值类型:" 的格式,"->" 标注返回值类型。
python
# 基础函数标注
def add(a: int, b: int) -> int:
return a + b
# 带默认值的参数标注(类型写在参数名后,默认值前)
def greet(name: str = "陌生人") -> str:
return f"你好,{name}!"
# 可选参数(允许为 None)
from typing import Optional
def get_user(id: int) -> Optional[dict]: # 返回字典或 None
if id <= 0:
return None
return {"id": id, "name": "张三"}
2、不定参数标注
python
# 可变长度参数 *args(元组)和 **kwargs(字典)
def print_nums(*args: int) -> None: # *args 是整数元组,无返回值
for num in args:
print(num)
def print_info(**kwargs: str) -> None: # **kwargs 是字符串值的字典
for k, v in kwargs.items():
print(f"{k}: {v}")
print_nums(1, 2, 3) # 合法
print_info(name="张三", age="25") # 合法(age 传字符串也不会运行报错,但静态检查会提示)
3. 任意类型(兜底标注)
如果不确定类型,用 Any(需导入)标注 "任意类型都允许":
python
from typing import Any
def process_data(data: Any) -> Any:
# 处理任意类型的数据
return data
四、自定义类型 / 复杂类型
1、自定义类作为类型
标注自定义类的实例,直接用类名:
python
class Waveguide:
nc: float # 类内变量标注
t: float
def __init__(self, nc: float, t: float) -> None:
self.nc = nc
self.t = t
# 标注 Waveguide 实例
wg: Waveguide = Waveguide(1.5, 2e-6)
# 标注存储 Waveguide 实例的列表
wg_list: list[Waveguide] = [wg, Waveguide(1.45, 3e-6)]
2、联合类型(多种类型可选)
用 Union[类型1, 类型2](3.8-)或 类型1 | 类型2(3.10+)标注 "可以是多种类型之一":
python
# Python 3.8- 需导入 Union
from typing import Union
score: Union[int, float] = 98 # 可以是整数或浮点数
# Python 3.10+ 更简洁
score: int | float = 98.5
3. 类型别名(简化复杂类型)
给复杂类型起别名,提升可读性:
python
# 定义类型别名
from typing import List, Dict
ScoreDict = Dict[str, List[int]] # 字符串键,整数列表值的字典
# 使用别名
def get_class_scores() -> ScoreDict:
return {"一班": [90, 85, 95], "二班": [88, 92, 89]}