类型注解是 Python 3.5+ 引入的特性,允许为变量、函数参数和返回值等添加类型提示,提高代码的可读性和可维护性。
基础类型注解
变量类型注解
# 基础类型
name: str = "Alice"
age: int = 25
height: float = 1.75
is_student: bool = True
# 集合类型
from typing import List, Dict, Set, Tuple
numbers: List[int] = [1, 2, 3, 4, 5]
person: Dict[str, str] = {"name": "Bob", "city": "New York"}
unique_ids: Set[int] = {1, 2, 3, 4}
coordinates: Tuple[float, float] = (40.7128, -74.0060)
函数类型注解
def greet(name: str) -> str:
return f"Hello, {name}"
def calculate_area(length: float, width: float) -> float:
return length * width
def process_data(
data: List[int],
multiplier: float = 1.0
) -> Dict[str, float]:
return {
"sum": sum(data) * multiplier,
"average": (sum(data) / len(data)) * multiplier
}
高级类型注解
可选类型 (Optional)
from typing import Optional, Union
def find_user(user_id: int) -> Optional[str]:
"""可能返回字符串,也可能返回None"""
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)
# 等价写法
def find_user_v2(user_id: int) -> Union[str, None]:
users = {1: "Alice", 2: "Bob"}
return users.get(user_id)
联合类型 (Union)
from typing import Union
def process_value(value: Union[int, str, float]) -> str:
"""接受多种类型的参数"""
return str(value)
# Python 3.10+ 的简化写法
def process_value_v2(value: int | str | float) -> str:
return str(value)
任意类型 (Any)
from typing import Any
def flexible_function(data: Any) -> Any:
"""接受和返回任意类型"""
return data
复杂数据结构注解
嵌套类型
from typing import List, Dict, Tuple, Optional
# 复杂的嵌套结构
UserProfile = Dict[str, Union[str, int, List[str]]]
Coordinates = Tuple[float, float]
def create_user_profile(
name: str,
age: int,
hobbies: List[str],
location: Optional[Coordinates] = None
) -> UserProfile:
profile = {
"name": name,
"age": age,
"hobbies": hobbies,
"is_active": True
}
if location:
profile["location"] = location
return profile
类类型注解
class Person:
def __init__(self, name: str, age: int) -> None:
self.name: str = name
self.age: int = age
def get_birth_year(self) -> int:
from datetime import datetime
return datetime.now().year - self.age
def create_people() -> List[Person]:
return [Person("Alice", 25), Person("Bob", 30)]
泛型和类型变量
from typing import TypeVar, Generic, List
T = TypeVar('T') # 任意类型
U = TypeVar('U') # 另一个任意类型
class Stack(Generic[T]):
def __init__(self) -> None:
self.items: List[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
# 使用泛型类
int_stack: Stack[int] = Stack()
int_stack.push(1)
int_stack.push(2)
str_stack: Stack[str] = Stack()
str_stack.push("hello")
函数类型和回调
from typing import Callable, List
# 函数类型注解
MathOperation = Callable[[float, float], float]
def apply_operation(
numbers: List[float],
operation: MathOperation
) -> List[float]:
return [operation(x, x) for x in numbers]
def multiply(a: float, b: float) -> float:
return a * b
result = apply_operation([1, 2, 3], multiply)
现代 Python 类型特性 (3.8+)
字面量类型 (Literal)
from typing import Literal
HttpMethod = Literal["GET", "POST", "PUT", "DELETE"]
def make_request(
method: HttpMethod,
url: str
) -> None:
print(f"Making {method} request to {url}")
# 正确使用
make_request("GET", "https://example.com")
# make_request("PATCH", "https://example.com") # 类型检查会报错
最终类型 (Final)
from typing import Final
# 常量注解
MAX_SIZE: Final[int] = 100
DEFAULT_NAME: Final[str] = "Unknown"
class Database:
# 类常量
TIMEOUT: Final[int] = 30
数据类 (dataclass) 类型注解
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class User:
name: str
age: int
email: Optional[str] = None
tags: List[str] = None
def __post_init__(self):
if self.tags is None:
self.tags = []
# 使用数据类
user = User(name="Alice", age=25, email="alice@example.com")
类型检查工具
使用 mypy 进行类型检查
# 安装 mypy
pip install mypy
# 检查单个文件
mypy your_script.py
# 检查整个项目
mypy your_project/
# 严格模式
mypy --strict your_script.py
配置 mypy
在 pyproject.toml 或 mypy.ini 中配置:
[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
实际应用示例
from typing import List, Dict, Optional, Union
from datetime import datetime
class Order:
def __init__(
self,
order_id: str,
items: List[Dict[str, Union[str, int, float]]],
customer_email: str,
created_at: Optional[datetime] = None
) -> None:
self.order_id = order_id
self.items = items
self.customer_email = customer_email
self.created_at = created_at or datetime.now()
def get_total_price(self) -> float:
return sum(item.get('price', 0) * item.get('quantity', 1)
for item in self.items)
def to_dict(self) -> Dict[str, Union[str, float, List]]:
return {
"order_id": self.order_id,
"total_price": self.get_total_price(),
"items": self.items,
"created_at": self.created_at.isoformat()
}
def process_orders(
orders: List[Order],
discount: float = 0.0
) -> Dict[str, float]:
"""处理订单并返回统计信息"""
total_revenue = sum(order.get_total_price() * (1 - discount)
for order in orders)
return {
"total_orders": len(orders),
"total_revenue": total_revenue,
"average_order_value": total_revenue / len(orders) if orders else 0
}
最佳实践
-
逐步引入: 在现有项目中逐步添加类型注解
-
保持一致性: 团队中使用统一的类型注解风格
-
合理使用 Any: 尽量避免过度使用
Any类型 -
利用工具: 使用 mypy 等工具进行静态类型检查
-
文档补充: 类型注解不能完全替代文档,复杂逻辑仍需注释
882

被折叠的 条评论
为什么被折叠?



