| name | python-patterns |
| description | Use when writing, reviewing, or refactoring Python code, designing data classes, implementing decorators, or choosing concurrency patterns. Do NOT use for linter/formatter config (use python-code-style) or testing (use python-testing). |
| paths | **/*.py, **/pyproject.toml |
Python Development Patterns
ํ๋จ ๊ธฐ์ค๊ณผ ๊ท์น ์ค์ฌ. ๊ธฐ๋ณธ ๋ฌธ๋ฒ์ด ์๋, Claude๊ฐ ์ฌ๋ฐ๋ฅธ ์ ํ์ ํ๋๋ก ์๋ด.
Quick Start
When to Activate
- Python ์ฝ๋ ์์ฑ, ๋ฆฌ๋ทฐ, ๋ฆฌํฉํ ๋ง
- ๋ฐ์ดํฐ ๋ชจ๋ธ๋ง (dataclass vs NamedTuple vs TypedDict)
- ๋์์ฑ ๋ชจ๋ธ ์ ํ
- ํ์
ํํธ ์ ๋ต ๊ฒฐ์
- ์ฝ๋ ๋ฆฌ๋ทฐ
CRITICAL Rules
- NEVER mutable default arguments โ
def f(items=[]) ๊ธ์ง, items=None ์ฌ์ฉ
- NEVER bare
except: โ ํญ์ specific exception ๋ช
์
- ALWAYS chain exceptions โ
raise NewError(...) from e
- ALWAYS context managers for resources โ
with ๋ฌธ ํ์
- PREFER EAFP over LBYL โ
try/except > if exists (race condition ๋ฐฉ์ง)
- PREFER modern type hints (3.10+) โ
str | None > Optional[str]
- NEVER
from module import * โ ๋ช
์์ import๋ง
- ALWAYS
is None / is not None โ == None ๊ธ์ง
- PREFER
isinstance() over type() โ ์์ ์ฒด์ธ ์กด์ค
Type Hints
| Type Feature | Use When |
|---|
X | None | Optional value (3.10+) |
Protocol | Duck typing interface (structural subtyping) |
@override | Overriding parent method (3.12+) |
TypeIs | Type narrowing in both branches (3.13+) |
ParamSpec | Preserving decorator type signature |
type statement | Recursive/complex type aliases (3.12+, PEP 695) |
Legacy Optional, Union | Only for Python < 3.10 support |
Data Containers
Need a data container?
โโโ Immutable? โ NamedTuple or @dataclass(frozen=True)
โ โโโ Lightweight, tuple-like? โ NamedTuple
โ โโโ Methods, validation needed? โ @dataclass(frozen=True)
โโโ Dict-like (JSON mapping)? โ TypedDict
โโโ Need __post_init__ validation? โ @dataclass
โโโ Memory-critical (millions)? โ @dataclass(slots=True)
โโโ Simple grouping, no behavior? โ @dataclass
Error Handling
- Exception chaining ํ์:
raise NewError(...) from e
- Custom hierarchy:
AppError โ ValidationError, NotFoundError
- EAFP > LBYL (race condition ๋ฐฉ์ง)
- CRITICAL Rules #2, #3, #5 ์ฐธ์กฐ
Concurrency Decision
Need concurrent I/O?
โโโ Many connections (100+)? โ asyncio (TaskGroup)
โโโ Few connections? โ ThreadPoolExecutor
โโโ Simplest option? โ concurrent.futures.ThreadPoolExecutor
Need parallel computation?
โโโ Pure Python math? โ ProcessPoolExecutor
โโโ NumPy/pandas? โ threading (already releases GIL)
โโโ Python 3.13+ experimental? โ Free-threaded mode
Need both I/O + CPU?
โโโ asyncio + ProcessPoolExecutor via run_in_executor
See Concurrency Deep Dive for TaskGroup, Semaphore, producer-consumer pipeline.
Code Review Priorities
| Level | Examples | Action |
|---|
| CRITICAL | Mutable defaults, bare except, resource leak | Fix immediately |
| HIGH | Missing types, no exception chaining | Fix before merge |
| MEDIUM | Style violations, missing docs | Fix or TODO |
Gotchas
- โ mutable default argument (
def f(x=[])) โ None ๊ธฐ๋ณธ๊ฐ + ๋ด๋ถ ์์ฑ
- โ
type() ๋น๊ต โ isinstance() ์ฌ์ฉ
- โ bare
except: โ ์ต์ except Exception: ๋๋ ๊ตฌ์ฒด์ ์์ธ
- โ
== None ๋น๊ต โ is None ์ฌ์ฉ
- โ
CancellationError ์ผํค๊ธฐ (asyncio) โ ๋ฐ๋์ re-raise
Verification
์ฝ๋ ์์ฑ ํ ๋ฐ๋์ ์คํ:
ruff check .
ruff format --check .
pytest -x -q
mypy --strict src/
Cross-References