Python类型提示完全指南:让你的代码自己会说话
你还在靠猜理解别人写的函数吗?
def process_data(data):
return data.get("result", [])[0].get("value", 0)
看到这段代码,我血压都高了。这玩意儿到底期望什么输入?返回值是什么类型?data 这个字典里装的啥?
类型提示(Type Hints) 就是来解决这个问题的。
为什么你的代码需要类型提示?
很多人觉得 Python 是动态类型语言,写类型提示是多余。这话放在写脚本时没错,但一旦代码超过 500 行,或者团队协作,类型提示就是救命稻草。
类型提示的好处:- IDE 自动补全准确率翻倍
- 代码审查时一眼看懂意图
- 重构时自动检测类型错误
- 文档即代码,看注释不如看类型
基础类型提示
Python 3.5+ 开始支持类型提示,用法非常简单:
# 基础类型
name: str = "几行代码"
age: int = 25
price: float = 99.9
is_active: bool = True
# 函数参数和返回值
def greet(name: str) -> str:
return f"Hello, {name}"
冒号后面是参数类型,箭头后面是返回值类型。就这么简单。
常用容器类型
from typing import List, Dict, Set, Tuple, Optional
# 列表
def get_users() -> List[str]:
return ["Alice", "Bob"]
# 字典
def get_user_info() -> Dict[str, int]:
return {"age": 25, "score": 100}
# 可空类型
def find_user(user_id: int) -> Optional[str]:
if user_id > 0:
return "Alice"
return None # 明确返回 None
Optional[str] 等价于 Union[str, None],表示这个值要么是字符串,要么是 None。
复杂类型:Union 和 Literal
from typing import Union, Literal
# 多种可能类型
def parse_input(value: Union[str, int, float]) -> float:
return float(value)
# 限定值
def set_status(status: Literal["pending", "approved", "rejected"]) -> None:
print(f"Status: {status}")
# status 只能是这三个字符串之一,传别的会报错
set_status("pending") # OK
set_status("draft") # 报错!
高阶用法:Callable 和 TypeVar
from typing import Callable, TypeVar, Generic
# 函数作为参数
def execute_callback(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
result = execute_callback(lambda x, y: x + y, 1, 2) # 返回 3
# 泛型:自定义类型
T = TypeVar('T')
def get_first(items: List[T]) -> Optional[T]:
return items[0] if items else None
names: List[str] = ["a", "b"]
first_name = get_first(names) # first_name 类型是 str
实际项目示例
看一个完整的类型提示示例:
from typing import List, Dict, Optional, Literal
from dataclasses import dataclass
from datetime import datetime
@dataclass
class User:
id: int
name: str
email: str
created_at: datetime
is_active: bool = True
class UserRepository:
def __init__(self, connection: str) -> None:
self.conn = connection
def find_by_id(self, user_id: int) -> Optional[User]:
# 查询逻辑...
return None
def find_by_status(self, status: Literal["active", "inactive"]) -> List[User]:
# 查询逻辑...
return []
def create(self, name: str, email: str) -> User:
return User(
id=1,
name=name,
email=email,
created_at=datetime.now()
)
使用 @dataclass 配合类型提示,代码既简洁又清晰。
别踩坑:类型提示的常见误区
1. 类型提示不执行,运行时不检查def add(a: int, b: int) -> int:
return a + b
# 随便传,运行时不会报错!
result = add("hello", "world") # 返回 "helloworld"
要想真正检查类型,得用 mypy 或 pyright。
2. 不要过度标注# 过度标注 - 没必要
count: int = 0
name: str = "test"
# 适度标注 - 关注函数接口
def process(items: List[Dict[str, Any]]) -> List[str]:
...
3. typing 别名要在文件顶部定义# 好的做法
from typing import Dict, List
UserDict = Dict[str, str]
UserList = List[UserDict]
def get_users() -> UserList:
...
配置 IDE 类型检查
VS Code + Pylance 插件已经默认支持类型检查。PyCharm 也能很好地识别类型提示。
如果你想更严格,可以用 mypy:
pip install mypy
mypy your_file.py
总结
类型提示不是什么高深技术,就是让代码自解释。当你养成写类型提示的习惯后:
- 三个月后再看自己的代码,不用猜
- 团队成员接手你的代码,不用问
- 重构时工具帮你检查,不用怕
好代码不需要太多注释,好的类型提示本身就是注释。
如果觉得有用,欢迎点赞、在看、转发。有问题评论区见!