查看: 125|回复: 1

Python类型注解完全指南:从基础语法到高级泛型、TypedDict和异步代码实战

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
Python 作为动态类型语言,灵活性高但类型安全性不足。类型注解(Type Hints)自 Python 3.5 引入,允许开发者为变量、函数参数和返回值添加类型信息,从而提升代码可读性、IDE 支持、静态类型检查、文档质量和团队协作效率。本文从基础到高级应用全面解析 Python 类型注解,涵盖变量注解、函数注解、泛型、联合类型、TypedDict、数据类、回调函数、协议、类型检查工具及实际 Web API 和异步代码示例。

一、基础类型注解

变量注解:
  1. name: str = "Alice"
  2. age: int = 25
  3. height: float = 1.75
  4. is_student: bool = True
  5. # 容器类型需从 typing 导入
  6. from typing import List, Dict, Tuple, Set
  7. numbers: List[int] = [1, 2, 3, 4, 5]
  8. user_data: Dict[str, str] = {"name": "Bob", "email": "bob@example.com"}
  9. coordinates: Tuple[float, float] = (10.5, 20.3)
  10. unique_ids: Set[int] = {1, 2, 3, 4}
  11. # Python 3.10+ 可选类型简化
  12. maybe_name: str | None = None  # 等价于 Optional[str]
复制代码

函数注解:
  1. def greet(name: str) -> str:
  2.     return f"Hello, {name}!"
  3. def calculate_stats(numbers: List[float]) -> Tuple[float, float, float]:
  4.     if not numbers:
  5.         return 0.0, 0.0, 0.0
  6.     return sum(numbers)/len(numbers), min(numbers), max(numbers)
  7. def create_user(username: str, email: str, age: int = 18, is_active: bool = True) -> Dict[str, any]:
  8.     return {"username": username, "email": email, "age": age, "is_active": is_active}
复制代码

二、高级类型注解

泛型(Generic Types)允许编写可复用的类型安全组件。通过 TypeVar 和 Generic 实现:
  1. from typing import TypeVar, Generic, List
  2. T = TypeVar('T')
  3. class Stack(Generic[T]):
  4.     def __init__(self) -> None:
  5.         self._items: List[T] = []
  6.     def push(self, item: T) -> None:
  7.         self._items.append(item)
  8.     def pop(self) -> T:
  9.         return self._items.pop()
  10.     def is_empty(self) -> bool:
  11.         return len(self._items) == 0
  12. int_stack: Stack[int] = Stack()
  13. str_stack: Stack[str] = Stack()
复制代码

联合类型与可选类型:
  1. from typing import Union, Optional, Any, List, Dict
  2. def process_value(value: Union[int, str, List[int]]) -> str:
  3.     if isinstance(value, int):
  4.         return f"整数: {value}"
  5.     elif isinstance(value, str):
  6.         return f"字符串: {value}"
  7.     else:
  8.         return f"列表: {value}"
  9. def find_user(user_id: int) -> Optional[Dict[str, Any]]:
  10.     users = {1: {"name":"Alice","age":25}, 2: {"name":"Bob","age":30}}
  11.     return users.get(user_id)
  12. # Python 3.10+ 简化语法
  13. from typing import Union  # 或直接用 |
  14. def process_data(data: int | str | None) -> str:
  15.     if data is None:
  16.         return "无数据"
  17.     return f"数据: {data}"
复制代码

类型别名与 NewType:类型别名提高复杂类型可读性,NewType 创建语义不同的子类型,用于严格类型区分。
  1. UserId = int
  2. UserName = str
  3. def get_user_name(user_id: UserId) -> UserName:
  4.     return f"User{user_id}"
  5. from typing import NewType
  6. UserId = NewType('UserId', int)
  7. AdminId = NewType('AdminId', int)
  8. def create_user(user_id: UserId) -> None: ...
  9. def create_admin(admin_id: AdminId) -> None: ...
  10. user_id = UserId(123)
  11. admin_id = AdminId(456)
  12. create_user(user_id)  # OK
  13. create_user(123)       # 类型检查器警告
复制代码

三、结构化类型注解

TypedDict 用于定义字典结构,支持可选字段(NotRequired):
  1. from typing import TypedDict, NotRequired
  2. class UserProfile(TypedDict):
  3.     username: str
  4.     email: str
  5.     age: int
  6.     is_active: bool
  7.     bio: NotRequired[str]
  8. def update_profile(profile: UserProfile) -> None:
  9.     print(f"更新用户: {profile['username']}")
  10. user: UserProfile = {"username":"alice","email":"a@e.com","age":25,"is_active":True}
复制代码

数据类(Dataclass)结合类型注解:
  1. from dataclasses import dataclass, field
  2. from typing import ClassVar, Final, List
  3. @dataclass
  4. class Product:
  5.     name: str
  6.     price: float
  7.     description: str = ""
  8.     tags: List[str] = field(default_factory=list)
  9.     tax_rate: ClassVar[float] = 0.1
  10.     MAX_PRICE: Final[float] = 10000.0
  11.     def total_price(self, quantity: int = 1) -> float:
  12.         if self.price > self.MAX_PRICE:
  13.             raise ValueError(f"价格不能超过{self.MAX_PRICE}")
  14.         return self.price * quantity * (1 + self.tax_rate)
  15. product = Product(name="笔记本电脑", price=5000.0, description="高性能", tags=["电子"])
复制代码

四、回调函数与高阶函数类型注解
  1. from typing import Callable, List
  2. NumberTransformer = Callable[[float], float]
  3. def apply_transform(numbers: List[float], transform: NumberTransformer) -> List[float]:
  4.     return [transform(n) for n in numbers]
  5. def double(x: float) -> float: return x*2
  6. def square(x: float) -> float: return x**2
  7. apply_transform([1.0,2.0], double)
复制代码

装饰器类型注解:
  1. from functools import wraps
  2. def log_execution(func: Callable) -> Callable:
  3.     @wraps(func)
  4.     def wrapper(*args, **kwargs):
  5.         print(f"执行函数: {func.__name__}")
  6.         result = func(*args, **kwargs)
  7.         return result
  8.     return wrapper
  9. @log_execution
  10. def calculate_sum(a: int, b: int) -> int: return a+b
复制代码

五、协议(Protocol)与结构化子类型

Protocol 允许定义结构类型,无需继承即可实现接口,类似 Go 的隐式实现。
  1. from typing import Protocol, List
  2. @runtime_checkable
  3. class Drawable(Protocol):
  4.     def draw(self) -> None: ...
  5.     @property
  6.     def area(self) -> float: ...
  7. class Circle:
  8.     def __init__(self, radius: float): self.radius = radius
  9.     def draw(self) -> None: print(f"绘制圆形,半径: {self.radius}")
  10.     @property
  11.     def area(self) -> float: return 3.14159 * self.radius**2
  12. class Rectangle:
  13.     def __init__(self, width, height): self.width=width; self.height=height
  14.     def draw(self): print(f"绘制矩形,宽:{self.width},高:{self.height}")
  15.     @property
  16.     def area(self): return self.width*self.height
  17. def render_shapes(shapes: List[Drawable]) -> None:
  18.     for shape in shapes:
  19.         shape.draw()
  20.         print(f"面积: {shape.area}")
  21. render_shapes([Circle(5.0), Rectangle(4.0,6.0)])
复制代码

六、类型检查工具

Mypy 基础使用:
  1. pip install mypy
  2. mypy your_script.py
  3. mypy --strict your_script.py
  4. mypy --html-report report/ your_project/
复制代码

pyright 配置文件(pyrightconfig.json):
  1. {
  2.   "include": ["src"],
  3.   "exclude": ["**/__pycache__", "**/.pytest_cache"],
  4.   "typeCheckingMode": "strict",
  5.   "pythonVersion": "3.10",
  6.   "reportMissingImports": true,
  7.   "reportUnusedImport": true
  8. }
复制代码

代码中忽略类型检查:
  1. from typing import cast, Any, no_type_check
  2. value: Any = get_data()  # type: ignore
  3. result: int = value + 10
  4. typed_data = cast(List[int], data)
  5. @no_type_check
  6. def legacy_function(x):
  7.     return x + "字符串"
复制代码

七、实际应用示例

Web API 使用 FastAPI + Pydantic 类型注解:
  1. from fastapi import FastAPI, Query, Path
  2. from pydantic import BaseModel, Field
  3. from typing import Annotated
  4. app = FastAPI()
  5. class UserCreate(BaseModel):
  6.     username: str = Field(..., min_length=3, max_length=50)
  7.     email: str = Field(..., regex=r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
  8.     age: int = Field(..., ge=0, le=150)
  9.     tags: list[str] = Field(default_factory=list)
  10. class UserResponse(BaseModel):
  11.     id: int
  12.     username: str
  13.     email: str
  14.     age: int
  15.     created_at: str
  16. @app.post("/users/", response_model=UserResponse)
  17. async def create_user(user: UserCreate) -> UserResponse:
  18.     return UserResponse(id=1, username=user.username, email=user.email, age=user.age, created_at="2024-01-01T00:00:00")
  19. @app.get("/users/{user_id}")
  20. async def get_user(user_id: Annotated[int, Path(title="用户ID", ge=1)], include_details: Annotated[bool, Query(False)] = False) -> dict[str, Any]:
  21.     return {"id": user_id, "username": "test_user", "include_details": include_details}
复制代码

异步代码类型注解:
  1. import asyncio
  2. from typing import AsyncIterator, Awaitable
  3. from contextlib import asynccontextmanager
  4. async def fetch_data(url: str) -> dict[str, Any]:
  5.     await asyncio.sleep(0.1)
  6.     return {"url": url, "data": "示例数据"}
  7. async def process_items(items: list[str]) -> AsyncIterator[str]:
  8.     for item in items:
  9.         await asyncio.sleep(0.01)
  10.         yield f"处理: {item}"
  11. @asynccontextmanager
  12. async def database_connection(db_url: str) -> AsyncIterator[dict]:
  13.     connection = {"url": db_url, "connected": True}
  14.     try:
  15.         yield connection
  16.     finally:
  17.         connection["connected"] = False
  18. async def main() -> None:
  19.     urls = ["https://api.example.com/data1", "https://api.example.com/data2"]
  20.     tasks: list[Awaitable[dict]] = [fetch_data(url) for url in urls]
  21.     results = await asyncio.gather(*tasks)
  22.     async with database_connection("postgresql://localhost/db") as db:
  23.         print(f"连接到数据库: {db['url']}")
  24.         async for result in process_items(["item1","item2"]):
  25.             print(result)
  26. if __name__ == "__main__":
  27.     asyncio.run(main())
复制代码

八、最佳实践与常见陷阱

最佳实践:渐进式采用,从关键函数开始;保持项目内注解风格一致;使用类型别名和泛型提高可读性和复用性;定期运行类型检查并集成到 CI/CD。

常见陷阱:
1. 过度使用 Any:应使用 TypeVar 或具体类型。
2. 忽略容器元素类型:应写 list[str] 而非 list。
3. 循环引用:使用字符串字面量或 from __future__ import annotations。
  1. # 正确做法:字符串字面量
  2. class TreeNode:
  3.     def __init__(self, children: list["TreeNode"]): ...
  4. # 或使用 future
  5. from __future__ import annotations
  6. class TreeNode:
  7.     def __init__(self, children: list[TreeNode]): ...
复制代码

九、未来发展方向

Python 类型注解持续演进,3.10+ 简化联合语法,3.11+ 增加 Self 类型,3.12+ 强化参数规范。开发者应紧跟版本更新,合理利用特性提升代码健壮性。

通过本文的系统梳理,你可以从基础变量注解到高级泛型、TypedDict、Protocol、异步代码类型检查全面掌握 Python 类型注解,并在实际项目中有效应用。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python类型注解完全指南:从基础语法到高级泛型、TypedDict和异步代码实战

这篇指南写得非常全面!从基础语法到 TypedDict、泛型,再到不同 Python 版本的语法简化,都梳理得很清楚,对新手和想系统复习的人都很友好。你特意提到了 `NewType` 用于语义区分,这个部分很多入门教程容易忽略,确实能帮助写出更严格的代码。另外,后面预告的异步代码实战也很让人期待,这种把类型注解和实际 Web API、异步场景结合起来的例子,往往比单纯讲解语法更有启发性。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-11 13:43 , Processed in 0.029453 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部