05 - 类型注解与工具¶
学习时间: 1小时 重要性: ⭐⭐⭐⭐ 提高代码质量和可维护性
🎯 学习目标¶
- 掌握类型注解的基本语法
- 学会使用typing模块
- 理解dataclasses的用法
📝 类型注解基础¶
基本类型注解¶
Python
# Python 3.9+ 推荐:直接使用内置类型的泛型语法
# 无需从 typing 导入 List, Dict 等(已不推荐)
# 变量注解
name: str = "张三"
age: int = 25
height: float = 1.75
is_student: bool = True
# 函数注解
def greet(name: str) -> str:
return f"Hello, {name}!"
def calculate_sum(numbers: list[int]) -> int:
return sum(numbers)
# 可选类型(Python 3.10+ 推荐用 X | None)
def find_user(user_id: int) -> str | None:
if user_id == 1:
return "张三"
return None
# 多种类型(Python 3.10+ 使用 |)
def process(value: int | str) -> str:
return str(value)
# Python 3.9 兼容写法(使用 typing 模块)
from typing import Optional, Union
def find_user_compat(user_id: int) -> Optional[str]: # 等价于 str | None
return None
常用类型¶
Python
from typing import Any
from collections.abc import Callable
# 列表(Python 3.9+)
numbers: list[int] = [1, 2, 3]
names: list[str] = ["张三", "李四"]
# 字典
config: dict[str, Any] = {"name": "test", "count": 10}
scores: dict[str, int] = {"张三": 85, "李四": 90}
# 元组
point: tuple[int, int] = (10, 20)
rgb: tuple[int, int, int] = (255, 128, 0)
# 集合
unique_numbers: set[int] = {1, 2, 3}
# 可调用类型
# Callable[[参数类型列表], 返回类型]:表示接受两个int参数、返回int的函数
def apply(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
# Any类型(慎用)
def process_any(value: Any) -> None:
pass
🎯 泛型和TypeVar¶
Python
from typing import TypeVar, Generic
T = TypeVar("T") # 定义类型变量T,用于泛型编程,表示"任意类型"
def get_first(items: list[T]) -> T:
return items[0]
# 泛型类
class Box(Generic[T]): # 继承Generic[T]使类成为泛型类,T在实例化时由参数推断
def __init__(self, content: T):
self.content = content
def get(self) -> T:
return self.content
box_int = Box(42) # Box[int]
box_str = Box("hello") # Box[str]
📦 dataclasses - 数据类¶
基本用法¶
Python
from dataclasses import dataclass
@dataclass # @dataclass自动生成__init__、__repr__等常用方法
class Student:
name: str
age: int
grades: list[int]
def average_grade(self) -> float:
return sum(self.grades) / len(self.grades) if self.grades else 0
# 自动生成__init__, __repr__, __eq__等方法
student = Student("张三", 20, [85, 90, 78])
print(student) # Student(name='张三', age=20, grades=[85, 90, 78])
print(student.average_grade()) # 84.333...
# 自动比较
student1 = Student("张三", 20, [85])
student2 = Student("张三", 20, [85])
print(student1 == student2) # True
高级特性¶
Python
from dataclasses import dataclass, field
@dataclass
class DataProcessor:
name: str
cache: dict = field(default_factory=dict) # 可变默认值
items: list[int] = field(default_factory=list)
count: int = 0
readonly: int = field(init=False) # 只读,不在__init__中
def __post_init__(self):
"""初始化后处理"""
self.readonly = 42
# 使用
processor = DataProcessor("processor1")
print(processor) # DataProcessor(name='processor1', cache={}, items=[], count=0, readonly=42)
🎨 Enum - 枚举类型¶
Python
from enum import Enum, auto
class Status(Enum):
PENDING = auto()
RUNNING = auto()
COMPLETED = auto()
FAILED = auto()
# 使用
status = Status.RUNNING
print(status) # Status.RUNNING
print(status.value) # 2
# 比较
if status == Status.RUNNING:
print("正在运行")
# 在函数中使用
def update_status(status: Status):
if status == Status.COMPLETED:
print("任务完成")
elif status == Status.FAILED:
print("任务失败")
update_status(Status.COMPLETED)
💡 实用场景¶
场景1: 配置类¶
Python
from dataclasses import dataclass
@dataclass
class ModelConfig:
"""模型配置"""
model_name: str
learning_rate: float = 0.001
batch_size: int = 32
epochs: int = 100
device: str = "cpu"
checkpoint_path: str | None = None
# 使用
config = ModelConfig(
model_name="ResNet50",
learning_rate=0.0001,
device="cuda"
)
def train_model(config: ModelConfig):
print(f"训练模型: {config.model_name}")
print(f"学习率: {config.learning_rate}")
train_model(config)
场景2: 类型验证装饰器¶
Python
from typing import get_type_hints
from functools import wraps
def validate_types(func):
"""运行时类型验证"""
@wraps(func) # @wraps保留被装饰函数的元信息(名称、文档字符串等)
def wrapper(*args, **kwargs):
hints = get_type_hints(func) # 在运行时获取函数的类型注解字典
# 验证参数
for param_name, param_type in hints.items():
if param_name == "return":
continue
value = kwargs.get(param_name)
if value is not None and not isinstance(value, param_type):
raise TypeError(
f"{param_name} should be {param_type}, got {type(value)}"
)
return func(*args, **kwargs)
return wrapper
@validate_types
def process_data(name: str, count: int) -> None:
print(f"Processing {count} items for {name}")
process_data(name="test", count=10) # OK
# process_data(name="test", count="10") # TypeError
📝 练习¶
- 为你的项目添加完整的类型注解
- 创建一个配置dataclass
- 实现类型验证装饰器
🎯 自我检查¶
- 能正确使用类型注解
- 理解typing模块的常用类型
- 能使用dataclasses简化代码
- 知道何时使用枚举
📚 延伸阅读¶
🎉 恭喜完成阶段2!¶
你已经完成了标准库实用指南的学习!
接下来建议你: 1. 回顾总结 - 整理这个阶段的笔记 2. 实际应用 - 用标准库写一个工具脚本 3. 进入阶段3 - 数据科学核心库