本文へ移動
cccskills
無料GitHub で公開

python

Idiomatic programming style, patterns, and conventions for Python development. Trigger when: - Writing, refactoring, reviewing, or debugging Python code. - Files matching the pattern **/*.py (including requirements.txt, pyproject.toml, setup.py) are in the workspace or referenced. - Tasks involve: python, pytest, pip, uv, virtualenv, flake8, black, mypy. - Prompt contains keywords: python, py, pep8, typing, list comprehension, decorator, generator, asyncio, yield, poetry.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md19.3 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Python Language Idioms

Work with the language. Lean into duck typing, generators, context managers, and the standard library. Write code that reads like pseudocode — if it needs a comment to explain what it does, rewrite it.


Core Philosophy

  • Readability is a feature — code is read far more than it is written; optimize for the reader
  • Explicit over implicit — no magic, no hidden state, no clever tricks
  • Flat over nested — avoid deep indentation; early returns, guard clauses, comprehensions
  • Composition over inheritance — functions, protocols, and dataclasses beat class hierarchies
  • Standard library first — reach for builtins and stdlib before adding dependencies

Formatting

Let the formatter handle it. Pick one formatter project-wide and enforce it in CI.

ruff check .          # Lint
ruff format .         # Format
black .               # Alternative formatter

Non-Negotiables

RuleStandard
Indentation4 spaces. Tabs are prohibited.
Operator spacingx = y * 12 + 13, not x=y*12+13
Quote stylePick single or double project-wide; enforce via formatter. PEP 8 is deliberately silent.
Line lengthConfigure in formatter (88 for black/ruff, 79 for strict PEP 8). Don't manually wrap.
Importsisort-ordered: stdlib → third-party → local. One import per line for from imports.

Naming

Conventions

ScopeStyleExample
Modules, packagessnake_casecrypto_key.py, utils/
Functions, methodssnake_case (verbs)get_url(), calculate_checksum()
Variablessnake_case (nouns)raw_payload, user_registry
ClassesPascalCaseHttpClient, TokenParser
ConstantsSCREAMING_SNAKEMAX_RETRIES, DEFAULT_TIMEOUT
Private_leading_underscore_internal_cache, _validate()
Name-mangled__double_leading__secret (rarely needed)
Dunder__name__Reserved for the language. Never invent new ones.

The Verb-Noun Rule

Functions are actions → verbs. Variables are data → nouns. If a function name is a noun, it's probably a property.

Shadowing Built-ins (Prohibited)

Redefining these names breaks built-in functionality within scope and causes non-deterministic bugs:

id, type, len, range, list, dict, str, int, float, min, max, abs, set, map, filter, input, open, hash, format, next, iter, sum, any, all, dir, vars, help

Use descriptive alternatives: user_id, item_type, name_list, count.

Natural Phrasing

✅ Idiomatic❌ Avoid
if x not in yif not x in y
if x != yif not x == y
if x is not Noneif not x is None

Boolean and Comparison Idioms

Scenario❌ Wrong✅ IdiomaticWhy
Truthinessif x == True:if x:if evaluates truthiness directly
Falsinessif x == False:if not x:not is the logical inverter
None checkif x == None:if x is None:is checks identity; == can be overridden by __eq__
Empty checkif len(seq) == 0:if not seq:Empty collections are falsy
Type checktype(x) == intisinstance(x, int)Respects inheritance

Data Modeling

When to Use What

TypeUse WhenKey Trait
@dataclassMutable data with behaviorAuto-generates __init__, __repr__, __eq__
@dataclass(frozen=True)Immutable value objectsHashable, safe as dict keys
NamedTupleLightweight immutable recordsTuple-compatible, unpacking works
TypedDictTyped dict shapes (JSON, APIs)Runtime is still a plain dict
Plain dictDynamic/unknown keysNo structure guarantees
from dataclasses import dataclass, field

@dataclass(frozen=True, slots=True)
class Token:
    kind: str
    value: str
    line: int = 0

__slots__

Use slots=True on dataclasses (3.10+) or define __slots__ manually. It prevents dynamic attribute creation, reduces memory, and speeds up attribute access:

# ✅ With slots — fixed attributes, lower memory
@dataclass(slots=True)
class Point:
    x: float
    y: float

# ❌ Without slots — __dict__ per instance, allows typos like p.z = 3

Functions

Arguments and Returns

# ✅ Type-annotated at boundaries
def parse_config(raw: str, *, strict: bool = False) -> Config:
    ...

# ✅ Keyword-only after * — prevents positional misuse
def connect(host: str, port: int, *, timeout: float = 30.0) -> Connection:
    ...
  • Use * to force keyword-only arguments when order could be confused
  • Use / (3.8+) for positional-only when the parameter name is an implementation detail
  • Return None explicitly when a function can return None — don't rely on implicit fallthrough

Default Mutable Arguments (Critical)

# ❌ DANGEROUS — shared across all calls
def append_to(item, target=[]):
    target.append(item)
    return target

# ✅ Sentinel pattern
def append_to(item, target: list | None = None):
    if target is None:
        target = []
    target.append(item)
    return target

Properties

Use @property for computed attributes. Use @cached_property (3.8+) when the result is expensive and stable:

class Circle:
    def __init__(self, radius: float):
        self.radius = radius

    @property
    def area(self) -> float:
        return math.pi * self.radius ** 2

Iterators and Comprehensions

Comprehensions

Prefer comprehensions for simple transforms. Use explicit loops when the logic needs if/else branching or side effects:

# ✅ Clear — single transform + filter
names = [u.name for u in users if u.is_active]

# ✅ Dict comprehension
lookup = {u.id: u for u in users}

# ✅ Set comprehension
unique_tags = {tag for post in posts for tag in post.tags}

# ❌ Nested comprehension that requires mental parsing
result = [f(x) for x in [g(y) for y in items if h(y)] if p(x)]
# → Use intermediate variables or a generator pipeline instead

Generators

Use generators for lazy evaluation over large or infinite sequences. They consume O(1) memory:

# ✅ Generator expression — lazy, memory-efficient
total = sum(order.amount for order in orders)

# ✅ Generator function — for complex logic
def read_chunks(path: str, size: int = 8192):
    with open(path, 'rb') as f:
        while chunk := f.read(size):
            yield chunk

itertools

Reach for itertools before rolling your own iteration logic:

FunctionPurpose
chainConcatenate iterables
isliceSlice without materializing
groupbyGroup sorted items by key
productCartesian product
starmapmap() with argument unpacking
batched (3.12+)Fixed-size chunks

Context Managers

Use with for any resource that needs cleanup — files, locks, connections, transactions:

# ✅ Automatic cleanup
with open('data.json') as f:
    data = json.load(f)

# ✅ Multiple resources
with open('in.txt') as src, open('out.txt', 'w') as dst:
    dst.write(src.read())

Writing Context Managers

For simple cases, use contextlib.contextmanager:

from contextlib import contextmanager

@contextmanager
def temporary_directory():
    path = tempfile.mkdtemp()
    try:
        yield path
    finally:
        shutil.rmtree(path)

For classes, implement __enter__ and __exit__. For async resources, use async with and __aenter__ / __aexit__.


Async Patterns

async/await

Prefer async/await for I/O-bound concurrency:

import asyncio

async def fetch_user(session: aiohttp.ClientSession, uid: str) -> User:
    async with session.get(f'/api/users/{uid}') as resp:
        resp.raise_for_status()
        return User(**(await resp.json()))

Concurrent Operations

PatternBehaviorUse When
asyncio.gather(*coros)Runs concurrently, fails fastAll must succeed
asyncio.TaskGroup (3.11+)Structured concurrency, auto-cancelPrefer over gather
asyncio.to_thread(fn)Offloads blocking I/O to thread poolWrapping sync libraries

Rules

  • Never mix asyncio.run() with a running loop — it raises RuntimeError
  • Never call blocking I/O in an async function without to_thread — it blocks the entire loop
  • Use async for for async iteration and async with for async context managers
  • Cancellation: Handle asyncio.CancelledError explicitly when cleanup is needed

Structural Pattern Matching (3.10+)

match/case is a structural destructuring tool, not a switch statement. It combines type checking, attribute extraction, and branching in one expression:

match command:
    case {"action": "move", "direction": str(d)}:
        move(d)
    case {"action": "quit"}:
        sys.exit(0)
    case Point(x=0, y=y):
        print(f"On y-axis at {y}")
    case [first, *rest] if len(rest) > 2:
        process_batch(first, rest)
    case _:
        raise ValueError(f"Unknown command: {command}")

Key Facts

FactDetail
Single subjectmatch targets exactly one variable — no scattered conditions
DestructuringSequences, mappings, and class attributes are unpacked declaratively
Guardscase X if condition: for fine-grained filtering
Wildcard _Can appear multiple times in one pattern (unlike assignment)
Class matchingUses __match_args__ or @dataclass for positional patterns

[!WARNING] Strings are NOT sequences in match/case. Unlike standard unpacking, case [x, y] will never match a two-character string. This is intentional — it prevents a class of bugs where strings are accidentally iterated as character arrays.


Type System

Python's type system is gradual — annotations are optional but invaluable for static analysis. The runtime remains dynamic; types don't enforce anything at execution time.

Annotation Rules

  • Annotate function signatures — parameters and return types
  • Let inference handle locals — don't annotate obvious assignments
  • Use modern syntax — int | str not Union[int, str], str | None not Optional[str] (3.10+)

Key Constructs

ConstructUse
type Vector = list[float] (3.12+)Type alias — equivalent name for a type
NewType('UserId', int)Distinct subtype — a raw int won't satisfy UserId
ProtocolStructural subtyping ("static duck typing")
@runtime_checkableEnables isinstance checks against a Protocol
TypeIs (3.13+)Preferred over TypeGuard — supports intersection narrowing and negative narrowing
TypeGuardOlder narrowing — only narrows in the positive branch

Any vs object

Any disables type checking. object is type-safe — it requires narrowing before use. Prefer object when you mean "anything" but still want the checker engaged.

The TYPE_CHECKING Pattern

Avoid import cycles by guarding type-only imports:

from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from expensive_module import HeavyType

def process(item: HeavyType) -> None:
    ...

String Handling

f-strings (Default)

f-strings are the standard for string interpolation. They are fast, readable, and support format specs:

name = "world"
print(f"Hello, {name!r}")       # repr
print(f"Pi is {math.pi:.4f}")   # format spec
print(f"{value:>10,}")          # right-aligned with comma separator

Template Strings (3.14+)

T-strings (t"...") produce a Template object instead of a str, enabling handler-based interpolation. Use them when interpolating untrusted input — f-strings evaluate eagerly and cannot be intercepted:

from string.templatelib import Template, Interpolation

def sanitized_sql(template: Template) -> tuple[str, tuple]:
    parts, params = [], []
    for item in template:
        if isinstance(item, str):
            parts.append(item)
        elif isinstance(item, Interpolation):
            parts.append("?")
            params.append(item.value)
    return "".join(parts), tuple(params)

query, params = sanitized_sql(t"SELECT * FROM users WHERE id = {user_input}")

Legacy

  • str.format() — use only when format spec is dynamic (known at runtime, not write-time)
  • % formatting — legacy only. Do not use in new code.

Error Handling

Specific Exceptions

Catch specific exceptions. Never use bare except: or except Exception: pass:

# ✅ Specific, with context
try:
    config = load_config(path)
except FileNotFoundError:
    raise ConfigError(f"Config not found: {path}") from None
except json.JSONDecodeError as e:
    raise ConfigError(f"Malformed config at {path}: {e}") from e

# ❌ Silent swallow — hides every possible failure
try:
    config = load_config(path)
except:
    pass

Exception Chaining

Use from to preserve the causal chain. Use from None to intentionally suppress it:

# Chain — preserves original traceback
raise AppError("operation failed") from original_error

# Suppress — when the original is noise for the caller
raise AppError("not found") from None

Custom Exceptions

Define domain-specific exceptions. Keep hierarchies shallow:

class AppError(Exception):
    """Base for application errors."""

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

Anti-Patterns

Anti-PatternDescriptionRemedy
Mutable default argsdef f(x=[]): — shared across callsUse None sentinel
Bare exceptexcept: catches SystemExit, KeyboardInterruptCatch specific types
Shadowing builtinslist = [1, 2, 3]Use descriptive names
God classMonolithic class with 20+ methodsDecompose into functions and smaller classes
Stringly typedUsing strings where enums or types belongenum.Enum, NewType, Literal
Deep nesting4+ levels of indentationEarly returns, guard clauses, helper functions
import *Pollutes namespace, breaks toolingExplicit named imports
Type: ignore spamSilencing every type errorFix the types or narrow properly
Overusing classesClasses with no state (just methods)Use plain functions
isinstance chainsLong if isinstance(x, A) ... elif isinstance(x, B)match/case or dispatch

Tooling

ruff check . --fix    # Lint + autofix
ruff format .         # Format
mypy .                # Type check (strict)
pyright .             # Alternative type checker
pytest                # Run tests
pytest --cov          # Coverage
uv run ...            # Fast dependency management and execution

Quick Reference

  • 4-space indent — never tabs, never 2-space
  • snake_case — functions, variables, modules
  • PascalCase — classes only
  • if x is None — not == None
  • if not seq — not len(seq) == 0
  • @dataclass — not manual __init__
  • with — for any resource needing cleanup
  • Comprehensions — for simple transforms, loops for complex logic
  • Generators — for lazy iteration over large data
  • f-strings — default interpolation; T-strings for untrusted input
  • int | str — not Union[int, str] (3.10+)
  • * separator — force keyword-only args when order is ambiguous
  • Never shadow builtins — id, type, list, dict, etc.
  • Never except: pass — catch specific, handle or propagate

These idioms refine but are subordinate to the Code-Edit Constraints.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

ai-audit

無料

SOP for auditing AI-generated code. Trigger when: - Reviewing, refactoring, or cleaning up AI-generated code to prevent regressions or hallucinated APIs. - Prompt contains: /ai-audit, code audit, AI cleanup, common flaws.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

api-audit

無料

Protocol for auditing API surface coherence and type safety. Trigger when: - Evaluating API designs, interface type safety, or design elegance. - Prompt contains: /api-audit, API surface, API coherence, type safety.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

boundary

無料

Normative sufficiency conditions for Initial Boundary Conditions (IBCs) and the SOP for the cheap-tier boundary refinement loop (/boundary). Trigger when: - Crafting, auditing, or refining a prompt/IBC destined for an expensive (architect-class) model or an autonomous worker dispatch. - Evaluating whether a task frame is sufficient to bound an agent walk. - Prompt contains: /boundary, IBC, initial boundary condition, boundary contract, sufficiency conditions, worker prompt, prompt refinement.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

campaign

無料

SOP for the architect-tier campaign workflow (/campaign): exhaustive survey, mitigation planning, tiered orchestration, and reconciliation. Trigger when: - Running a multi-workstream initiative where an expensive architect-tier council surveys, plans, emits worker prompts, and judges landed work. - Conducting production-readiness assessments that fan out into autonomous mitigation dispatches across model tiers. - Prompt contains: /campaign, campaign workflow, survey, orchestrate, reconcile, premise freshness, tier routing, worker IBC, scratch.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

chronicle

無料

Maintain and update the persistent project chronicle (docs/chronicle.md). Trigger when: - The human requests a history summary or chronicle update. - Starting work on a new codebase and needing context on its evolution. - Prompt contains keywords: /chronicle, chronicle, project history, git log summary, history summary.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

Rules, conventions, and constraints for formatting git commit messages and committing at logical boundaries. Trigger when: - Drafting, revising, or validating git commit messages. - Pausing at commit boundaries under the CORE or CONTINUE workflows. - Evaluating whether a changeset should be split into multiple commits. - Prompt contains keywords: commit message, git commit, conventional commits, commit hygiene, commit guidelines, logical boundary, spaghetti diff, atomic commit, commit boundary.

日本語の概要は準備中です。原文の説明を表示しています。

nrdxp/predicate102026年9月1日 更新

nrdxp のスキルをすべて見る

このスキルの問題を報告する