This skill should be used when the user asks to "write Python code", "create a Python module", "set up a Python project", "review Python code", "refactor Python", "add type hints", "fix Python style", or when generating any Python source code. Provides modern Python 3.12+ best practices covering syntax, type hints, error handling, project structure, and idiomatic patterns. Does not cover any specific library or framework.
Pure Python best practices for writing clean, idiomatic, and type-safe code. All guidance targets Python 3.12+ and covers only the standard language and stdlib — no third-party libraries or frameworks.
| Element | Convention | Example |
|---|---|---|
| Module | snake_case | data_loader.py |
| Package | lowercase | utils/, core/ |
| Class | PascalCase | UserAccount |
| Function/Method | snake_case | get_user_by_id() |
| Variable | snake_case | retry_count |
| Constant | UPPER_SNAKE | MAX_RETRIES |
| Type alias | PascalCase | type UserId = int |
| Private | _leading | _internal_cache |
| Name-mangled | __double | __secret (rarely needed) |
| Dunder | __name__ | Reserved for Python protocols |
Prefix boolean variables and functions with is_, has_, can_, or should_.
| Legacy | Modern (3.12+) |
|---|---|
Union[X, Y] | X | Y |
Optional[X] | X | None |
TypeAlias = ... | type Alias = ... |
List[str], Dict[str, int] | list[str], dict[str, int] |
Tuple[int, ...] | tuple[int, ...] |
if/elif/elif chains on a value | match/case |
os.path.join() | pathlib.Path |
"{}".format(x) | f"{x}" |
Use match/case for value dispatch, destructuring, and type narrowing — not as a simple switch replacement. See references/modern-syntax.md for detailed patterns.
match command:
case {"action": "move", "direction": str(d)}:
handle_move(d)
case {"action": "quit"}:
handle_quit()
case _:
handle_unknown(command)type statement (3.12+)type Vector = list[float]
type Result[T] = T | Error
type Handler[**P] = Callable[P, Awaitable[None]]Apply type hints to all function signatures, class attributes, and module-level variables. Omit return type only for __init__.
def calculate_total(items: list[float], *, tax_rate: float = 0.0) -> float:
...Key rules:
list[str], dict[str, int], tuple[int, ...], set[str]X | None instead of Optional[X]type statement for aliases, not bare assignmentProtocol over ABC when only structural typing is needed@override decorator (3.12+) when overriding base class methodsSelf for methods returning the instance typeFor comprehensive typing patterns including generics, Protocol, TypeGuard, TypeVar, and ParamSpec, consult references/type-hints.md.
Define domain errors as a hierarchy inheriting from a project-level base:
class AppError(Exception):
"""Base for all application errors."""
class ValidationError(AppError):
"""Invalid input data."""
class NotFoundError(AppError):
"""Requested resource does not exist."""except:.raise NewError(...) from original.ExceptionGroup and except* for concurrent error aggregation.with statement) for resource cleanup — avoid manual try/finally.try:
async with TaskGroup() as tg:
tg.create_task(validate_name(data))
tg.create_task(validate_email(data))
except* ValidationError as eg:
errors = eg.exceptionsPrefer dataclasses for data containers. Use __slots__ for memory-critical paths.
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class Coordinate:
x: float
y: float
label: str = ""
tags: list[str] = field(default_factory=list)frozen=True for value objects and immutable data.slots=True (3.10+) to reduce memory and prevent attribute typos.kw_only=True when the class has more than 3 fields.field(default_factory=...) for mutable defaults.Follow the src layout for any project intended to be packaged or tested:
project-name/
├── pyproject.toml
├── src/
│ └── package_name/
│ ├── __init__.py
│ ├── core/
│ ├── models/
│ └── utils/
├── tests/
│ ├── conftest.py
│ ├── unit/
│ └── integration/
└── scripts/Key conventions:
pyproject.toml.src/ layout prevents accidental imports from the working directory.__init__.py files minimal — define the public API, not implementation.users/ over services/).For complete project structure guidance including pyproject.toml conventions, module organization, and entry points, consult references/project-structure.md.
pathlib.Path for all file system operations.enum.Enum / enum.StrEnum for fixed sets of values.contextlib.contextmanager for simple resource management.functools.cache / functools.lru_cache for memoization.itertools for iterator composition.collections.abc for abstract container checks.total = sum(item.price for item in cart) # generator — no intermediate listif (match := pattern.search(line)) is not None:
process(match.group(1))__all__ for public API__all__ = ["UserService", "create_user", "UserError"]For comprehensive patterns including Protocols, ABCs, descriptors, context managers, enums, and more, consult references/patterns.md.
For detailed guidance beyond this overview, consult:
references/modern-syntax.md — Structural pattern matching, type statement, exception groups, @override, f-string detailsreferences/type-hints.md — Generics, Protocol, TypeGuard, TypeVar, ParamSpec, Self, Overloadreferences/patterns.md — Idiomatic patterns: Protocols, enums, context managers, generators, pathlib, ABCreferences/project-structure.md — pyproject.toml conventions, src layout, module organization, entry points, __init__.py patterns70de68f
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.