关于 python-type-safety
面向 Python 开发者的类型安全指导技能,涵盖注解、泛型、协议和类型收窄,并介绍如何用 mypy 或 pyright 检查代码。
主要功能
- 01为公共 API 添加类型注解
- 02构建泛型可复用类
- 03用协议定义结构化接口
- 04通过守卫收窄类型
- 05配置严格类型检查
适用场景
- 01为现有代码添加类型提示
- 02设计可复用的类型安全库
- 03配置 mypy 或 pyright 检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ full-stack-skills/ python-skills --skill python-type-safety安装后在 Claude Code 中输入/python-type-safety确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSE.txtagents/openai.yamlexamples/advanced-usage.mdbasic-usage.mdintegration.mdreferences/details.md详细介绍
来源声明:本技能内容源自 wshobson/agents (MIT License, Copyright (c) 2024 Seth Hobson;完整许可文本见同目录
LICENSE.txt)。 使用、修改与再分发须遵守该 MIT 许可条款并保留版权声明。
中文描述
本技能提供全栈开发相关的最佳实践和模式指导。
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 - 使用类型编写文档 - 类型是可强制执行的文档
能力边界
✅ 擅长处理
- 全栈开发相关的最佳实践
- 代码架构设计指导
- 性能优化建议
⚠️ 需要素材
- 具体的项目上下文
- 技术栈信息
❌ 超出范围
- 非技术领域的业务决策
- 具体的代码实现(仅提供指导)
工作流程
步骤 1:需求分析
理解项目需求和技术约束
步骤 2:架构设计
设计系统架构和组件划分
步骤 3:实现指导
提供具体的实现建议和代码模式
步骤 4:代码审查
审查代码质量和最佳实践遵循情况
步骤 5:优化建议
提供性能优化和改进建议
注意事项
1. 过度设计
避免在简单场景中使用复杂的设计模式
2. 性能忽视
不要忽视性能优化,特别是在生产环境中
3. 安全考虑
始终考虑安全性和数据保护
4. 测试覆盖
确保有足够的测试覆盖,特别是边界情况
5. 文档维护
保持文档与代码同步更新