Python Type Safety

作者 wshobson46891e7e60da无许可证收录于 2026年10月8日更新于 2026年10月8日

Python type safety with type hints, generics, protocols, and strict type checking. Use when adding type annotations, implementing generic classes, defining structural interfaces, or configuring mypy/pyright.

AI 生成的概览

指导 Python 类型注解、泛型、协议以及 mypy/pyright 严格类型检查。

功能
该技能提供使用 Python 类型系统的指导,涵盖类型注解、泛型、协议和类型收窄。它给出为公共签名添加注解、使用现代联合类型语法、编写泛型类以及配置 mypy 或 pyright 严格检查等模式。产出的是代码示例和建议,本身不运行任何工具。
适用场景
适用于为现有 Python 代码添加类型提示、创建泛型或可复用类、用协议定义结构化接口,或配置 mypy/pyright 严格检查时。也适合在理解类型收窄与类型守卫,或构建类型安全的 API 和库时使用。
运行要求
无需脚本或运行时依赖,仅为说明性内容。应用这些指导需要 Python 项目,并可选用 mypy 或 pyright 进行严格检查。

Python Type Safety

Leverage Python's type system to catch errors at static analysis time. Type annotations serve as enforced documentation that tooling validates automatically.

When to Use This Skill

  • Adding type hints to existing code
  • Creating generic, reusable classes
  • Defining structural interfaces with protocols
  • Configuring mypy or pyright for strict checking
  • Understanding type narrowing and guards
  • Building type-safe APIs and libraries

Core Concepts

1. Type Annotations

Declare expected types for function parameters, return values, and variables.

2. Generics

Write reusable code that preserves type information across different types.

3. Protocols

Define structural interfaces without inheritance (duck typing with type safety).

4. Type Narrowing

Use guards and conditionals to narrow types within code blocks.

Quick Start

python
def get_user(user_id: str) -> User | None:    """Return type makes 'might not exist' explicit."""    ...
# Type checker enforces handling None caseuser = get_user("123")if user is None:    raise UserNotFoundError("123")print(user.name)  # Type checker knows user is User here

Fundamental Patterns

Pattern 1: Annotate All Public Signatures

Every public function, method, and class should have type annotations.

python
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."""        ...

Use mypy --strict or pyright in CI to catch type errors early. For existing projects, enable strict mode incrementally using per-module overrides.

Pattern 2: Use Modern Union Syntax

Python 3.10+ provides cleaner union syntax.

python
# 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]:    ...

Pattern 3: Type Narrowing with Guards

Use conditionals to narrow types for the type checker.

python
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]

Pattern 4: Generic Classes

Create type-safe reusable containers.

python
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 typesdef 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

Detailed worked examples and patterns

Detailed sections (starting with ## Advanced Patterns) live in references/details.md. Read that file when the navigation summary above is insufficient.

Best Practices Summary

  1. Annotate all public APIs - Functions, methods, class attributes
  2. Use T | None - Modern union syntax over Optional[T]
  3. Run strict type checking - mypy --strict in CI
  4. Use generics - Preserve type info in reusable code
  5. Define protocols - Structural typing for interfaces
  6. Narrow types - Use guards to help the type checker
  7. Bound type vars - Restrict generics to meaningful types
  8. Create type aliases - Meaningful names for complex types
  9. Minimize Any - Use specific types or generics. Any is acceptable for truly dynamic data or when interfacing with untyped third-party code
  10. Document with types - Types are enforceable documentation

来源与署名

来源:wshobson/agents位于plugins/python-development/skills/python-type-safety提交46891e7

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架