python

Guide for writing clean, efficient, idiomatic Python 3.11+ code. Enforces type hints, Pydantic v2 for APIs, comprehensions over loops, EAFP error handling. Triggers on "python", "pythonic", ".py file", "write python", "python script", "python function", "python class", "pydantic", "fastapi", "pytest", "type hint", "typing", "dataclass", "async def", "asyncio", "aiohttp", "comprehension", "generator", "decorator", "context manager", "with statement", "exception handling", "try except", "raise", "logging python", "argparse", "click", "typer", "__init__", "__main__", "import", "from import", "python module", "python package", "requirements.txt", "pyproject.toml", "ruff", "mypy", "black", "isort", "python testing", "fixture", "parametrize", "edit .py", "modify .py", "update .py", "change .py", "fix .py", "refactor .py", "edit python", "modify python", "update python", "change python", "fix python code". PROACTIVE: MUST invoke BEFORE using Write OR Edit on ANY .py file.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "python" with this command: npx skills add mauromedda/agent-toolkit/mauromedda-agent-toolkit-python

ABOUTME: Comprehensive skill for idiomatic Python best practices

ABOUTME: Covers loops, dicts, comprehensions, typing, Pydantic v2, error handling

Idiomatic Python Best Practices

Target: Python 3.11+ with modern tooling (uv, Pydantic v2, type hints).

Detailed patterns: See references/pydantic-patterns.md and references/advanced-patterns.md


Quick Reference

PatternPythonic WayAvoid
Iterationfor item in items:for i in range(len(items)):
Index + Valuefor i, v in enumerate(seq):Manual counter
Dict Accessd.get("key", default)if "key" in d: d["key"]
Dict Iterationfor k, v in d.items():for k in d: v = d[k]
Swap Variablesa, b = b, atemp = a; a = b; b = temp
Build Strings"".join(parts)s += part in loop
Membershipx in set_or_dictx in list (for large)
File I/Owith open(...) as f:Manual f.close()
Truthinessif items:if len(items) > 0:
None Checkif x is None:if x == None:

🛑 FILE OPERATION CHECKPOINT (BLOCKING)

Before EVERY Write or Edit tool call on a .py file:

╔══════════════════════════════════════════════════════════════════╗
║  🛑 STOP - PYTHON SKILL CHECK                                    ║
║                                                                  ║
║  You are about to modify a .py file.                             ║
║                                                                  ║
║  QUESTION: Is /python skill currently active?                    ║
║                                                                  ║
║  If YES → Proceed with the edit                                  ║
║  If NO  → STOP! Invoke /python FIRST, then edit                  ║
║                                                                  ║
║  This check applies to:                                          ║
║  ✗ Write tool with file_path ending in .py                       ║
║  ✗ Edit tool with file_path ending in .py                        ║
║  ✗ ANY Python file, regardless of conversation topic             ║
║                                                                  ║
║  Examples that REQUIRE this skill:                               ║
║  - "update the schemas" (edits schemas.py)                       ║
║  - "fix the import" (edits any .py file)                         ║
║  - "add logging" (edits Python code)                             ║
╚══════════════════════════════════════════════════════════════════╝

Why this matters: In session 1ea73ffd, Claude edited 3+ Python files without invoking the Python skill, leading to potential style/pattern inconsistencies.


🔄 RESUMED SESSION CHECKPOINT

┌─────────────────────────────────────────────────────────────┐
│  SESSION RESUMED - PYTHON SKILL VERIFICATION                │
│                                                             │
│  Before continuing:                                         │
│  1. Type hints on all functions?                            │
│  2. Pydantic v2 for API validation?                         │
│  3. ABOUTME headers on new files?                           │
│  4. Run: ruff check <file>.py && mypy <file>.py             │
│  5. Re-invoke /python if skill context was lost             │
└─────────────────────────────────────────────────────────────┘

Core Patterns

Iteration

# Direct iteration
for item in items:
    process(item)

# With index
for i, item in enumerate(items):
    print(f"{i}: {item}")

# Parallel iteration
for name, score in zip(names, scores, strict=True):
    process(name, score)

# Reversed/sorted (no copy)
for item in reversed(items):
    process(item)

Dictionaries

# Safe access with default
port = config.get("port", 8080)

# Initialize-if-missing
groups: dict[str, list[str]] = {}
groups.setdefault(category, []).append(item)

# Merge dicts (Python 3.9+)
merged = defaults | overrides

# Dict comprehension
squares = {n: n**2 for n in range(10)}

Comprehensions

# List comprehension
squared = [x**2 for x in numbers]
evens = [x for x in numbers if x % 2 == 0]

# Generator expression (memory efficient)
total = sum(x**2 for x in range(1_000_000))
any_match = any(item.is_valid for item in items)

# Set comprehension
unique_domains = {email.split("@")[1] for email in emails}

Unpacking

# Basic
x, y, z = coordinates
first, *rest = items
a, b = b, a  # Swap

# Dict unpacking
combined = {**defaults, **overrides}
connect(**config)  # Pass as kwargs

Type Hints

Basic Types

def greet(name: str, times: int = 1) -> str:
    return f"Hello, {name}! " * times

def process(items: list[str]) -> dict[str, int]:
    return {item: len(item) for item in items}

Optional and Union

def find_user(user_id: int) -> User | None:
    return db.get(user_id)

def process(value: int | str | None) -> str:
    if value is None:
        return "none"
    return str(value)

Generic Collections

from collections.abc import Sequence, Mapping, Iterable, Callable

def process_items(items: Sequence[str]) -> list[str]:
    return [item.upper() for item in items]

def apply_func(data: Iterable[int], func: Callable[[int], int]) -> list[int]:
    return [func(x) for x in data]

Pydantic v2 (Quick Reference)

Use Pydantic for API validation and serialization. Full patterns: references/pydantic-patterns.md

from pydantic import BaseModel, Field, EmailStr

class User(BaseModel):
    id: int
    email: EmailStr
    name: str = Field(min_length=1, max_length=100)
    is_active: bool = True

# Parse and validate
user = User.model_validate({"id": 1, "email": "test@example.com", "name": "Alice"})

# Serialize
user.model_dump()       # To dict
user.model_dump_json()  # To JSON

When to Use What

Data TypeUse
API request/responsePydantic BaseModel
External JSON/dict shapeTypedDict (type hints only)
Internal data containerdataclass
Configurationpydantic-settings

Error Handling

Catch Specific Exceptions

try:
    value = int(user_input)
except ValueError:
    print("Invalid number")
except TypeError:
    print("Wrong type")

# DON'T: bare except
try:
    value = int(user_input)
except:  # Catches KeyboardInterrupt too!
    pass

EAFP (Pythonic)

# EAFP: Easier to Ask Forgiveness than Permission
try:
    value = mapping[key]
except KeyError:
    value = default

# vs LBYL: Look Before You Leap
if key in mapping:
    value = mapping[key]
else:
    value = default

Custom Exceptions

class ValidationError(Exception):
    def __init__(self, field: str, message: str):
        self.field = field
        self.message = message
        super().__init__(f"{field}: {message}")

def validate_email(email: str) -> str:
    if "@" not in email:
        raise ValidationError("email", "Must contain @")
    return email.lower()

Context Managers

# File handling (always use with)
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()

# Multiple files
with open("in.txt") as infile, open("out.txt", "w") as outfile:
    outfile.write(infile.read().upper())

String Handling

# f-strings
name = "Alice"
score = 95.678
print(f"Score: {score:.2f}")  # 95.68
print(f"{1000000:,}")  # 1,000,000
print(f"{x=}")  # Debug: x=42

# String building (use join, not +=)
result = " ".join(parts)

Best Practices

DO

  • Use meaningful variable names
  • Prefer composition over inheritance
  • Keep functions small and focused
  • Use type hints consistently
  • Use pathlib.Path for file paths
  • Use logging instead of print

DON'T

  • Use mutable default arguments: def f(items=[]):
  • Modify lists while iterating
  • Use from module import *
  • Catch bare except:
  • Use eval() with untrusted input

Quality Tools

# Linting
ruff check .
ruff check --fix .

# Type checking
mypy src/

# Formatting
ruff format .

Advanced Patterns

See references/advanced-patterns.md for:

  • itertools (chain, islice, groupby, product)
  • functools (partial, lru_cache, cached_property)
  • collections (defaultdict, Counter, deque)
  • Custom context managers
  • Generator functions
  • Dataclasses
  • Enumerations
  • TypedDict for data contracts

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

spec-driven-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

web-automation

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

golang

No summary provided by upstream source.

Repository SourceNeeds Review
python | V50.AI