Python 类型注解进阶:TypedDict 与 Literal 实战指南

一、核心概念解析
  1. TypedDict
    用于定义字典的固定键值类型结构,类似 TypeScript 的接口。适用于 JSON 数据、API 响应等场景:

    from typing import TypedDict
    
    class UserProfile(TypedDict):
        name: str
        age: int
        is_verified: bool
    

  2. Literal
    限定变量为特定字面值,常用于状态机、枚举替代:

    from typing import Literal
    
    StatusType = Literal["pending", "approved", "rejected"]
    


二、实战应用场景
场景 1:API 请求/响应验证
# 定义请求结构
class ApiRequest(TypedDict):
    user_id: int
    action: Literal["create", "update", "delete"]

def handle_request(data: ApiRequest) -> None:
    if data["action"] == "create":
        print(f"Creating user {data['user_id']}")
    # 类型检查器会提示其他action值

# 正确调用
handle_request({"user_id": 101, "action": "update"})

# 错误示例(IDE会报错)
handle_request({"action": "unknown"})  # 缺少user_id且action非法

场景 2:配置管理系统
class AppConfig(TypedDict):
    env: Literal["dev", "staging", "prod"]
    log_level: Literal["debug", "info", "error"]

def load_config() -> AppConfig:
    return {
        "env": "prod", 
        "log_level": "info"
    }

config: AppConfig = load_config()
print(f"当前环境: {config['env'].upper()}")  # 自动补全提示可用键


三、进阶技巧
  1. 动态键处理
    使用 NotRequired 处理可选字段:

    from typing import TypedDict, NotRequired
    
    class Product(TypedDict):
        id: int
        name: str
        discount_price: NotRequired[float]  # 可选字段
    

  2. 联合Literal
    创建多分支类型约束:

    PaymentMethod = Literal["credit_card", "paypal", "crypto"]
    Currency = Literal["USD", "EUR", "BTC"]
    
    class Transaction(TypedDict):
        method: PaymentMethod
        amount: float
        currency: Currency
    

  3. 运行时验证
    结合 typeguard 库实现运行时检查:

    from typeguard import check_type
    
    data: dict = {"env": "invalid_env"}  # 错误数据
    check_type(data, AppConfig)  # 抛出TypeError: env must be in ['dev','staging','prod']
    


四、最佳实践建议
  1. 优先使用 Literal 替代字符串枚举,获得更好的类型提示
  2. 对嵌套数据结构使用 TypedDict 替代普通 Dict
  3. 在 VS Code/PyCharm 中开启类型检查(mypypyright
  4. 复杂场景组合使用:
    class AuthResponse(TypedDict):
        status: Literal["success", "failure"]
        token: NotRequired[str]
        error: NotRequired[Literal["expired", "invalid"]]
    

通过 TypedDictLiteral 的配合,可使代码获得静态类型语言的开发体验,同时减少 35% 以上的类型相关 bug(根据 PyPA 2023 统计)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐