python-code
Skill1 starsChanged 7 months agoMITView on GitHub
Write, refactor, and debug Python code following Pythonic best practices from the official Python style guide, Effective Python, and Fluent Python. Use this skill whenever the user writes, reviews, refactors, or debugs Python code, asks about Python patterns, idioms, or style, mentions writing a script/module/package in Python, or requests code that is "Pythonic." Applies to all Python 3.10+ code.
3 other projects use a version of this.
Adopted by
Most recently taken up by
- DongDuong2001/pudo-code-systemtheir own version, first seen Oct 13, 2026
- cognis-digital/skillsmiththeir own version, first seen Oct 11, 2026
- wachawo/claude-skillstheir own version, first seen May 5, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- DongDuong2001/pudo-code-system★ 5same name
- cognis-digital/skillsmith★ 0same name
- wachawo/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository4 other files it gives its agents.
- python-developerSkill
- skill-creatorSkill
- skill-evaluatorSkill
- vue3-sfcSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
26 rules. About 0 are common, 9 are distinctive, and 17 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
17
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 8
Write Python code the way experienced Pythonistas write it — idiomatic, clear, and grounded in the principles from Python's official docs, …
- Distinctive: line 23
Prefer flat structure over deep nesting.
- Very specific: line 28
Use collections (defaultdict, Counter, namedtuple, dataclasses) instead of manual dict tricks.
- Very specific: line 29
Use comprehensions and generator expressions instead of manual loops.
- Very specific: line 30
Use yield and generator functions for lazy pipelines — process data one item at a time without loading everything into memory.
- Very specific: line 31
Use context managers (with) for resource management — files, locks, connections.
- Very specific: line 32
Use the pathlib module instead of os.path for filesystem operations.
- Very specific: line 33
Use f-strings instead of .format() or % formatting.
- Very specific: line 34
Use match/case (3.10+) for destructuring structured data and replacing deep if/elif chains — it's cleaner than isinstance checks for …
- Very specific: line 41
Use type annotations. They communicate intent, enable static analysis, and cost nothing at runtime.
- Distinctive: line 48
Don't reach for a class just because Java would.
- Very specific: line 49
If it's just data, use a dataclass or NamedTuple.
- Distinctive: line 50
If it has behavior and state, a class makes sense.
- Distinctive: line 51
If you need a class, implement dunder methods so objects behave like native Python objects.
- Very specific: line 60
Use try/except/else/finally fully.
- Very specific: line 66
Use asyncio for I/O-bound work, concurrent.futures for CPU-bound work.
- Very specific: line 67
Prefer asyncio.TaskGroup (3.11+) over manual task creation — automatic cleanup and error propagation.
- Very specific: line 68
Never mix sync and async code casually.
- Distinctive: line 72
Follow PEP 8 as baseline, but go beyond it:
- Very specific: line 78
Type annotations: All function signatures. Use from __future__ import annotations for forward references.
- Distinctive: line 90
Docstrings: All public functions have Google-style docstrings.
- Very specific: line 132
Subclassing built-in types incorrectly: If you override __setitem__, you probably also need __getitem__, __delitem__, update, etc.
- Very specific: line 136
Missing reverse operators: If you implement __add__, Python falls back to __radd__ on the right operand when the left doesn't know how to …
- Very specific: line 137
__bool__vs__len__confusion: If both are defined, bool(obj) uses __bool__. - Distinctive: line 143
After writing or refactoring code, verify:
- Distinctive: line 148
Docstrings: All public functions have Google-style docstrings
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Python Code Skill
Write Python code the way experienced Pythonistas write it — idiomatic, clear, and grounded in the principles from Python's official docs, Effective Python (Brett Slatkin), and Fluent Python (Luciano Ramalho).
Why this skill exists
Python is deceptively simple. Code that runs isn't the same as code that's Pythonic. The difference shows up in readability, maintainability, and how well code plays with the rest of the ecosystem. This skill internalizes the accumulated wisdom from the language's core documentation and the two most respected Python methodology books, so every piece of Python code you write benefits from those insights without you having to look them up.
Core Principles
These principles guide every line of Python you write. When trade-offs arise, refer back to these.
1. Readability counts — it's the #1 priority
Code is read far more often than it's written. Optimize for the reader, not the writer. This means:
- Obvious over clever. A list comprehension that fits one line is great; a nested comprehension that requires a whiteboard to unpack is not.
- Naming matters.
users_by_regionbeatsdorgrp. If you need a comment to explain what a variable holds, the name is wrong. - Prefer flat structure over deep nesting. Guard clauses (early return) keep indentation shallow and logic linear.
2. Use Python's power — don't fight it
Python has rich built-in types and protocols. Leverage them instead of reinventing:
- Use
collections(defaultdict,Counter,namedtuple,dataclasses) instead of manual dict tricks. - Use comprehensions and generator expressions instead of manual loops. List comprehensions are more readable than
map+lambda, butmapis fine when you already have a callable (map(str, numbers)beats[str(n) for n in numbers]). - Use
yieldand generator functions for lazy pipelines — process data one item at a time without loading everything into memory.yield fromdelegates to sub-generators.itertools(chain,islice,groupby,tee) is the stdlib toolkit for building iterator pipelines. - Use context managers (
with) for resource management — files, locks, connections. - Use the
pathlibmodule instead ofos.pathfor filesystem operations. - Use f-strings instead of
.format()or%formatting. - Use
match/case(3.10+) for destructuring structured data and replacing deep if/elif chains — it's cleaner than isinstance checks for complex branching.
3. Functions are the unit of composition
Small, focused functions with clear input/output contracts beat monolithic blocks:
- Each function does one thing. If you're writing a docstring and need "and" to list what it does, split it.
- Return values are better than mutating arguments. Mutating arguments creates hidden coupling that's hard to debug.
- Use type annotations. They communicate intent, enable static analysis, and cost nothing at runtime.
def search(needle: str, haystack: list[str]) -> int:is self-documenting. - Separate I/O from logic. Functions that mix file reads, network calls, or database queries with business logic are hard to test and brittle to refactor. Keep pure-data functions (take data in, return data out) separate from I/O adapters (read file, write result). This way the core logic can be tested without mocking filesystem or network, and the I/O layer can be swapped (e.g., from local files to S3) without touching business rules.
- Choose the right callable form. Prefer closures for simple state capture (a counter, a callback with context) — they're lighter than a class. Use
@dataclassor a class only when you need multiple methods or a complex interface. Adef make_counter(start=0)returning an inner function is simpler than aCounterclass with__call__. - Keep function bodies under 30 lines (excluding docstrings). Long functions indicate mixed responsibilities — extract helpers. Guidelines: ≤ 10 lines ideal, 10-20 acceptable, 20-30 borderline, > 30 refactor. Exceptions: dispatch tables, data-driven logic (match/case, dict of handlers).
4. Classes when you need state; functions when you don't
Don't reach for a class just because Java would. Functions and simple data structures cover most needs:
- If it's just data, use a
dataclassorNamedTuple. - If it has behavior and state, a class makes sense. Keep inheritance shallow — composition over inheritance.
- If you need a class, implement dunder methods so objects behave like native Python objects. The minimum depends on the class's role:
- All classes:
__repr__— sorepr(obj)is useful in debugging and logging. - Data-like classes:
__eq__and__hash__(if immutable) — so they work in sets/dicts. - Container-like classes (hold items, support lookup):
__len__,__contains__,__getitem__— solen(cache),key in cache, andcache[key]work. Without these, users must remember custom method names likesize(),get()— a maintenance burden and a departure from Python conventions. - Callable objects:
__call__— when configuration + behavior makes sense.
- All classes:
5. Handle errors explicitly, fail fast
- Raise specific exceptions (
ValueError,KeyError, custom subclasses) — never bareexcept:. - Use
try/except/else/finallyfully. Theelseclause runs when no exception occurred, which is clearer than putting success logic inside thetry. - Validate inputs at system boundaries (public API, user input). Trust internal callers — don't sprinkle validation everywhere.
- Invalid input should raise, not silently adapt. When a caller passes
ttl=-5, raiseValueError("ttl must be positive, got -5")— don't silently treat it as "expire immediately." Silently reinterpreting invalid input hides bugs in the caller's code and makes diagnosing issues much harder. The exception message should include the actual value received so the caller can see what went wrong without adding print statements.
6. Concurrency and async with care
- Use
asynciofor I/O-bound work,concurrent.futuresfor CPU-bound work. - Prefer
asyncio.TaskGroup(3.11+) over manual task creation — automatic cleanup and error propagation. - Never mix sync and async code casually. If a function is async, everything it calls should be async or offloaded via
run_in_executor.
Code Style Rules
Follow PEP 8 as baseline, but go beyond it:
- Line length: 88 (Black default). Readability over arbitrary 80-char limits.
- Imports:
stdlib → third-party → local, each group separated by a blank line. Usefrom x import yfor specific names,import xfor module-level access. - String quotes: Consistent within a file. Don't mix without reason.
- Trailing commas: In multi-line collections, always. Makes diffs cleaner.
- Type annotations: All function signatures. Use
from __future__ import annotationsfor forward references. - Naming conventions:
| Element | Convention | Example |
| Variables | snake_case | task_id, is_complete |
| Functions | snake_case, verb prefix | get_tasks(), is_valid() |
| Classes | PascalCase | TaskRepository, ValidationError |
| Constants | UPPER_SNAKE | MAX_RETRIES, DEFAULT_TIMEOUT |
| Private | _prefix | _internal_method() |
| Boolean | is_, has_, can_ | is_valid, has_permission |
- Docstrings: All public functions have Google-style docstrings.
Patterns to Prefer
| Situation | Prefer | Avoid |
| Empty dict/list default param | None default + if x is None: x = {} | Mutable default def f(x={}) |
| Simple data container | @dataclass or NamedTuple | Manual __init__ |
| File paths | pathlib.Path | os.path string manipulation |
| Counting | Counter | dict with if key in d |
| Grouping | defaultdict(list) | if key not in d: d[key] = [] |
| Iteration with index | enumerate() | range(len()) |
| Parallel iteration | zip() | Index-based access |
| Conditional expression | x if cond else y | Multi-line if/else for simple cases |
| String building | "".join(parts) | += in a loop |
| Resource cleanup | with statement | Manual close() calls |
| Attribute access with default | getattr(obj, key, default) | try/except AttributeError for simple cases |
| Dictionary merging (3.9+) | d1 | d2 | d1.update(d2) for immutable merging |
| Container class interface | __len__, __contains__, __getitem__ | Custom size(), has(), get_by_key() methods |
| Structured data (evolving schema) | @dataclass with named fields | Tuple unpacking value, ts = entry |
| Business logic | Pure function taking/returning data | Function mixing I/O + computation |
| State capture (simple) | Closure with nonlocal | Full class for a counter/callback |
| Lazy data pipeline | Generator function with yield | Loading all data into a list |
| Operator overloading | __add__ + __radd__ + __iadd__ | Only __add__ (breaks 1 + obj) |
| Structural branching (3.10+) | match/case with destructuring | Deep isinstance + if/elif chains |
| Parallel IO | asyncio.gather | Sequential awaits |
| Blocking IO | ThreadPoolExecutor | asyncio for CPU-bound work |
| High-precision timing | time.perf_counter() | time.time() |
| Repeated computation | @functools.lru_cache | Manual memoization |
| Many instances | __slots__ | Regular __dict__ class |
| Context manager | @contextmanager + with | Manual try/finally cleanup |
Common Pitfalls to Avoid
These come from Effective Python and Fluent Python — each one has burned real projects:
- Mutable default arguments:
def f(items=[]):— the list persists across calls. UseNoneand create a new list inside the function. - Closures over loop variables:
lambda: iin a loop captures the variable, not the value. Uselambda i=i: iorfunctools.partial. isfor value comparison:ischecks identity, not equality.x is Noneis correct;x is 0orx is []is a bug.- Star imports in production code:
from module import *pollutes the namespace and hides dependencies. - Ignoring
__hash__when overriding__eq__: Unhashable objects break sets and dict keys. - Overusing
@property: Complex computation hidden behind property access is misleading. If it's expensive, make it a method. - Subclassing built-in types incorrectly: If you override
__setitem__, you probably also need__getitem__,__delitem__,update, etc. Consider composition instead. - Returning
True/Falsefrom__init__:__init__should returnNone. Raise exceptions on failure. - Using tuples for evolving data structures:
entry = (value, timestamp)is fine for a one-off script, but if the structure might grow (addcreated_at,hit_count), every unpacking site breaks. Use@dataclassfrom the start — the cost is trivial, the maintainability gain is real. - Coupling I/O with business logic: A function that reads a file, parses it, and returns results cannot be unit-tested without filesystem mocking. Split into:
parse_data(text: str) -> Result(testable) +read_and_parse(path: Path) -> Result(I/O adapter). The pure function is where bugs live; the I/O adapter is infrastructure. - Missing reverse operators: If you implement
__add__, Python falls back to__radd__on the right operand when the left doesn't know how to handle it. Without__radd__,1 + Money(5)works butMoney(5) + 1may not — a subtle asymmetry. __bool__vs__len__confusion: If both are defined,bool(obj)uses__bool__; if only__len__, zero is falsy. Forgetting__bool__when you have__len__leads to surprises — an empty-yet-valid container evaluates as falsy.- Forgetting
nonlocalin closures: A nested function that assigns to an outer variable needsnonlocal x— without it, the assignment creates a local variable that shadows the outer one, and the outer variable is never updated. __slots__blocksweakref: Adding__slots__removes__dict__and__weakref__by default. If you need weak references to instances, explicitly add__weakref__to__slots__.
Verification Checklist
After writing or refactoring code, verify:
- Type check:
pyrightpasses - Format:
ruff formatapplied - Lint:
ruff checkpasses - Docstrings: All public functions have Google-style docstrings
- Error handling: Specific exceptions, no bare
except: - No anti-patterns:
- ❌
items: list = [](mutable default) - ❌
def get_x(self): return self._x(use@property) - ❌
for i in range(len(items))(useenumerate) - ❌
x + " " + y(usef"{x} {y}") - ❌ Functions over 30 lines (extract helpers)
- ❌
- Function length: Each function body ≤ 30 lines (excluding docstring)
When to go deeper
This skill covers day-to-day Python writing. For specialized topics, read the relevant reference file:
references/advanced-types.md— Protocol, TypeVar, generics, overloads, type narrowingreferences/async-patterns.md— Async services, TaskGroup, mixing sync/asyncreferences/data-model.md— Dunder methods, descriptors, custom containersreferences/testing.md— Pytest fixtures, mocking, test patternsreferences/class-metaprogramming.md—__init_subclass__,match/casepattern matching,__class_getitem__references/effective-python/— Chapter-by-chapter patterns from Effective Python: pythonic thinking, lists/dicts, functions, classes, concurrency, error handling, performance, standard library
These are loaded only when needed to keep context lean — the core principles above cover the vast majority of Python code you'll write.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

