Python 类型注解:让你的代码自己说话
我是陈默,一个正拼命上岸的码农。
你有没有接过别人的代码,看着一个函数的参数,完全不知道该传什么进去?
def process(data):
这个 data 是什么?字符串?列表?字典?还是自定义对象?
你得翻遍整个文件,甚至打开数据库,才能猜出来。
这不是读代码,这是破案。
而 Python 的类型注解,就是让你不用再当侦探。
1. 类型注解是什么?
先看两段代码。
没有类型注解:
defget_user_age(user):
return user["age"]
有类型注解:
defget_user_age(user: dict) -> int:
return user["age"]
看到区别了吗?
第二段代码一眼就知道:参数 user 是个字典,返回值是整数。
类型注解不会改变代码的运行结果。Python 运行的时候会直接忽略它。
它的价值在别的地方——让你和你的队友少猜、少错、少吵架。
Python 从 3.5 版本开始正式支持类型注解。到现在,主流的开源项目几乎都在用。FastAPI、Pydantic 这些热门框架更是把类型注解当成了核心功能。
这不是可选项了。这是现代 Python 开发的基本功。
2. 基础用法:给变量和函数加上类型
变量的类型注解:
name: str = "陈默"
age: int = 28
score: float = 98.5
is_student: bool = True
简单直接。冒号后面写类型,等号后面赋值。
函数参数和返回值的类型注解:
defgreet(name: str) -> str:
returnf"你好,{name}"
defadd(a: int, b: int) -> int:
return a + b
参数后面的冒号标注参数类型,-> 标注返回值类型。
容器类型:
from typing import List, Dict, Tuple, Set
names: List[str] = ["张三", "李四"]
scores: Dict[str, int] = {"张三": 90, "李四": 85}
point: Tuple[float, float] = (3.14, 2.71)
unique_ids: Set[int] = {1, 2, 3}
List[str] 表示字符串列表,Dict[str, int] 表示键是字符串、值是整数的字典。
一目了然。
Python 3.9 以后,你甚至可以不用 typing 模块,直接用内置类型:
names: list[str] = ["张三", "李四"]
scores: dict[str, int] = {"张三": 90}
更简洁了。
3. 进阶用法:处理更复杂的场景
基础类型不够用?Python 提供了更强大的工具。
可选类型——Optional:
from typing import Optional
deffind_user(user_id: int) -> Optional[str]:
# 可能找到用户,也可能找不到
if user_id in database:
return database[user_id]
returnNone
Optional[str] 等价于 str | None。意思是返回值可能是字符串,也可能是 None。
这比在注释里写"可能返回 None"靠谱多了。
联合类型——Union:
from typing import Union
defprocess_input(data: Union[str, int]) -> str:
if isinstance(data, int):
return str(data)
return data
Python 3.10 以后,可以用更简洁的写法:
defprocess_input(data: str | int) -> str:
...
任意类型——Any:
from typing import Any
defprint_value(value: Any) -> None:
print(value)
当你真的不确定类型的时候,用 Any。但别滥用——用太多 Any 等于没加类型注解。
自定义类型:
classUser:
def__init__(self, name: str, age: int):
self.name = name
self.age = age
defget_user_name(user: User) -> str:
return user.name
直接用你的类名当类型。清晰又规范。
4. 实战:用 mypy 检查类型错误
类型注解写了但不检查,等于没写。
mypy 是 Python 最主流的静态类型检查工具。它会在代码运行之前帮你找出类型相关的错误。
安装 mypy:
pip install mypy
写一段有 bug 的代码:
defadd(a: int, b: int) -> int:
return a + b
result = add("hello", "world")
运行 mypy 检查:
mypy your_file.py
mypy 会立刻报错:Argument 1 to "add" has incompatible type "str"; expected "int"
你在运行代码之前就发现了问题。不用等到线上爆炸才发现传错了参数。
养成习惯—— 每次写完代码跑一下 mypy。把它加入你的开发流程,和测试一样重要。
最后
类型注解的本质是什么?
是沟通成本的降低。
代码被阅读的次数,远多于被编写的次数。你今天省下的那五秒钟不写类型的功夫,会让明天的你(或者你的同事)花五十分钟去理解。
回顾一下今天的内容:
- 基础类型用
str、int、float,容器类型用 List[str]、Dict[str, int] - 进阶场景用
Optional、Union、Any 和自定义类型 - 用 mypy 在运行前检查类型错误,把 bug 扼杀在摇篮里
现在打开你最近写的一个 Python 文件,给函数加上类型注解。你会发现代码立刻变得不一样了。
今天就到这里。
我是陈默,我们下期再见。
如果你觉得这篇文章有帮助,欢迎关注我。我会持续分享 Python 学习的干货。