关于 python-type-safety
面向 Python 开发者的类型安全技能,指导使用类型标注、泛型和协议来减少静态检查阶段的错误,并配置严格类型检查。
主要功能
- 01为公开 API 添加类型标注
- 02使用泛型编写可复用代码
- 03通过 Protocol 定义结构化接口
- 04用守卫条件收窄类型
- 05配置 mypy 或 pyright 严格检查
适用场景
- 01为现有 Python 代码补充类型提示
- 02构建保留类型信息的通用类
- 03为接口定义结构化类型
- 04在 CI 中逐步启用严格检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ wshobson/ agents --skill python-type-safety安装后在 Claude Code 中输入/python-type-safety确认已加载。
附带文件references/details.md
详细介绍
Python 类型安全
利用 Python 的类型系统在静态分析阶段捕获错误。类型注解可作为由工具自动验证的强制性文档。
何时使用此技能
- 为现有代码添加类型提示
- 创建泛型、可复用的类
- 使用协议定义结构化接口
- 配置 mypy 或 pyright 进行严格检查
- 理解类型收窄和类型守卫
- 构建类型安全的 API 和库
核心概念
1. 类型注解
为函数参数、返回值和变量声明预期类型。
2. 泛型
编写在不同类型之间保留类型信息的可复用代码。
3. 协议
在不使用继承的情况下定义结构化接口(带类型安全的鸭子类型)。
4. 类型收窄
使用类型守卫和条件判断在代码块内收窄类型。
快速开始
def get_user(user_id: str) -> User | None:
"""Return type makes 'might not exist' explicit."""
...
# Type checker enforces handling None case
user = get_user("123")
if user is None:
raise UserNotFoundError("123")
print(user.name) # Type checker knows user is User here
基本模式
模式 1:为所有公共签名添加注解
每个公共函数、方法和类都应有类型注解。
def get_user(user_id: str) -> User:
"""Retrieve user by ID."""
...
def process_batch(
items: list[Item],
max_workers: int = 4,
) -> BatchResult[ProcessedItem]:
"""Process items concurrently."""
...
class UserRepository:
def __init__(self, db: Database) -> None:
self._db = db
async def find_by_id(self, user_id: str) -> User | None:
"""Return User if found, None otherwise."""
...
async def find_by_email(self, email: str) -> User | None:
...
async def save(self, user: User) -> User:
"""Save and return user with generated ID."""
...
在 CI 中使用 mypy --strict 或 pyright 尽早捕获类型错误。对于现有项目,可通过按模块覆盖逐步启用严格模式。
模式 2:使用现代联合类型语法
Python 3.10+ 提供了更简洁的联合类型语法。
# Preferred (3.10+)
def find_user(user_id: str) -> User | None:
...
def parse_value(v: str) -> int | float | str:
...
# Older style (still valid, needed for 3.9)
from typing import Optional, Union
def find_user(user_id: str) -> Optional[User]:
...
模式 3:使用类型守卫进行类型收窄
使用条件判断为类型检查器收窄类型。
def process_user(user_id: str) -> UserData:
user = find_user(user_id)
if user is None:
raise UserNotFoundError(f"User {user_id} not found")
# Type checker knows user is User here, not User | None
return UserData(
name=user.name,
email=user.email,
)
def process_items(items: list[Item | None]) -> list[ProcessedItem]:
# Filter and narrow types
valid_items = [item for item in items if item is not None]
# valid_items is now list[Item]
return [process(item) for item in valid_items]
模式 4:泛型类
创建类型安全的可复用容器。
from typing import TypeVar, Generic
T = TypeVar("T")
E = TypeVar("E", bound=Exception)
class Result(Generic[T, E]):
"""Represents either a success value or an error."""
def __init__(
self,
value: T | None = None,
error: E | None = None,
) -> None:
if (value is None) == (error is None):
raise ValueError("Exactly one of value or error must be set")
self._value = value
self._error = error
@property
def is_success(self) -> bool:
return self._error is None
@property
def is_failure(self) -> bool:
return self._error is not None
def unwrap(self) -> T:
"""Get value or raise the error."""
if self._error is not None:
raise self._error
return self._value # type: ignore[return-value]
def unwrap_or(self, default: T) -> T:
"""Get value or return default."""
if self._error is not None:
return default
return self._value # type: ignore[return-value]
# Usage preserves types
def parse_config(path: str) -> Result[Config, ConfigError]:
try:
return Result(value=Config.from_file(path))
except ConfigError as e:
return Result(error=e)
result = parse_config("config.yaml")
if result.is_success:
config = result.unwrap() # Type: Config
详细示例与模式
详细章节(以 ## Advanced Patterns 开头)位于 references/details.md。当上述导航摘要不够用时,请阅读该文件。
最佳实践摘要
- 为所有公共 API 添加注解 - 函数、方法、类属性
- 使用
T | None- 用现代联合类型语法替代Optional[T] - 运行严格类型检查 - 在 CI 中使用
mypy --strict - 使用泛型 - 在可复用代码中保留类型信息
- 定义协议 - 为接口使用结构化类型
- 收窄类型 - 使用类型守卫帮助类型检查器
- 约束类型变量 - 将泛型限制为有意义的类型
- 创建类型别名 - 为复杂类型赋予有意义的名称
- 尽量减少
Any- 使用具体类型或泛型。对于真正动态的数据,或与无类型的第三方代码交互时,Any是可以接受的 - 用类型记录文档 - 类型是强制执行的文档
评论
支持 Markdown