Mmcp.market

python-patterns skill

by affaan-m·affaan-m/ECC·269k stars·MIT

Patrones idiomáticos de Python, estándares PEP 8, type hints y buenas prácticas para construir aplicaciones Python robustas, eficientes y mantenibles.

A100/100content scan

Is the python-patterns skill safe?

Clean: nothing in its files matched our rules. We read 1 file in the folder on 2026-09-28.

No findings.

Install the python-patterns skill

A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.

git clone --depth 1 https://github.com/affaan-m/ECC.git /tmp/ECC
mkdir -p ~/.claude/skills
cp -r /tmp/ECC/docs/es/skills/python-patterns ~/.claude/skills/python-patterns
available in every project

In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub

The instructions your agent would load

SKILL.md as published, without the frontmatter. Read it on GitHub

Patrones de Desarrollo Python

Patrones idiomáticos de Python y buenas prácticas para construir aplicaciones robustas, eficientes y mantenibles.

Cuándo Activar

  • Escribir código Python nuevo
  • Revisar código Python
  • Refactorizar código Python existente
  • Diseñar paquetes/módulos Python

Principios Fundamentales

1. La Legibilidad Cuenta

Python prioriza la legibilidad. El código debe ser obvio y fácil de entender.

# Bien: Claro y legible
def get_active_users(users: list[User]) -> list[User]:
    """Retorna solo los usuarios activos de la lista proporcionada."""
    return [user for user in users if user.is_active]


# Mal: Inteligente pero confuso
def get_active_users(u):
    return [x for x in u if x.a]

2. Explícito es Mejor que Implícito

Evitar la magia; ser claro sobre lo que hace el código.

# Bien: Configuración explícita
import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Mal: Efectos secundarios ocultos
import some_module
some_module.setup()  # ¿Qué hace esto?

3. EAFP - Es Más Fácil Pedir Perdón que Permiso

Python prefiere el manejo de excepciones sobre verificar condiciones.

# Bien: Estilo EAFP
def get_value(dictionary: dict, key: str) -> Any:
    try:
        return dictionary[key]
    except KeyError:
        return default_value

# Mal: Estilo LBYL (Look Before You Leap)
def get_value(dictionary: dict, key: str) -> Any:
    if key in dictionary:
        return dictionary[key]
    else:
        return default_value

Type Hints

Anotaciones de Tipo Básicas

from typing import Optional, List, Dict, Any

def process_user(
    user_id: str,
    data: Dict[str, Any],
    active: bool = True
) -> Optional[User]:
    """Procesa un usuario y retorna el User actualizado o None."""
    if not active:
        return None
    return User(user_id, data)

Type Hints Modernos (Python 3.9+)

# Python 3.9+ - Usar tipos built-in
def process_items(items: list[str]) -> dict[str, int]:
    return {item: len(item) for item in items}

# Python 3.8 y anteriores - Usar módulo typing
from typing import List, Dict

def process_items(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

Type Aliases y TypeVar

from typing import TypeVar, Union

# Type alias para tipos complejos
JSON = Union[dict[str, Any], list[Any], str, int, float, bool, None]

def parse_json(data: str) -> JSON:
    return json.loads(data)

# Tipos genéricos
T = TypeVar('T')

def first(items: list[T]) -> T | None:
    """Retorna el primer elemento o None si la lista está vacía."""
    return items[0] if items else None

Duck Typing Basado en Protocol

from typing import Protocol

class Renderable(Protocol):
    def render(self) -> str:
        """Renderiza el objeto a una cadena."""

def render_all(items: list[Renderable]) -> str:
    """Renderiza todos los elementos que implementan el protocolo Renderable."""
    return "\n".join(item.render() for item in items)

Patrones de Manejo de Errores

Manejo de Excepciones Específicas

# Bien: Capturar excepciones específicas
def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except FileNotFoundError as e:
        raise ConfigError(f"Archivo de config no encontrado: {path}") from e
    except json.JSONDecodeError as e:
        raise ConfigError(f"JSON inválido en config: {path}") from e

# Mal: except desnudo
def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except:
        return None  # ¡Fallo silencioso!

Encadenamiento de Excepciones

def process_data(data: str) -> Result:
    try:
        parsed = json.loads(data)
    except json.JSONDecodeError as e:
        # Encadenar excepciones para preservar el traceback
        raise ValueError(f"Error al parsear datos: {data}") from e

Jerarquía de Excepciones Personalizadas

class AppError(Exception):
    """Excepción base para todos los errores de la aplicación."""
    pass

class ValidationError(AppError):
    """Se lanza cuando falla la validación de entrada."""
    pass

class NotFoundError(AppError):
    """Se lanza cuando no se encuentra un recurso solicitado."""
    pass

# Uso
def get_user(user_id: str) -> User:
    user = db.find_user(user_id)
    if not user:
        raise NotFoundError(f"Usuario no encontrado: {user_id}")
    return user

Context Managers

Gestión de Recursos

# Bien: Usar context managers
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

# Mal: Gestión manual de recursos
def process_file(path: str) -> str:
    f = open(path, 'r')
    try:
        return f.read()
    finally:
        f.close()

Context Managers Personalizados

from contextlib import contextmanager

@contextmanager
def timer(name: str):
    """Context manager para medir el tiempo de un bloque de código."""
    start = time.perf_counter()
    yield
    elapsed = time.perf_counter() - start
    print(f"{name} tardó {elapsed:.4f} segundos")

# Uso
with timer("procesamiento de datos"):
    process_large_dataset()

Clases Context Manager

class DatabaseTransaction:
    def __init__(self, connection):
        self.connection = connection

    def __enter__(self):
        self.connection.begin_transaction()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            self.connection.commit()
        else:
            self.connection.rollback()
        return False  # No suprimir excepciones

# Uso
with DatabaseTransaction(conn):
    user = conn.create_user(user_data)
    conn.create_profile(user.id, profile_data)

Comprehensions y Generadores

List Comprehensions

# Bien: List comprehension para transformaciones simples
names = [user.name for user in users if user.is_active]

# Mal: Loop manual
names = []
for user in users:
    if user.is_active:
        names.append(user.name)

# Las comprehensions complejas deben expandirse
# Mal: Demasiado complejo
result = [x * 2 for x in items if x > 0 if x % 2 == 0]

# Bien: Usar una función generadora
def filter_and_transform(items: Iterable[int]) -> list[int]:
    result = []
    for x in items:
        if x > 0 and x % 2 == 0:
            result.append(x * 2)
    return result

Expresiones Generadoras

# Bien: Generador para evaluación lazy
total = sum(x * x for x in range(1_000_000))

# Mal: Crea una lista intermedia grande
total = sum([x * x for x in range(1_000_000)])

Funciones Generadoras

def read_large_file(path: str) -> Iterator[str]:
    """Lee un archivo grande línea por línea."""
    with open(path) as f:
        for line in f:
            yield line.strip()

# Uso
for line in read_large_file("huge.txt"):
    process(line)

Data Classes y Named Tuples

Data Classes

from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class User:
    """Entidad de usuario con __init__, __repr__ y __eq__ automáticos."""
    id: str
    name: str
    email: str
    created_at: datetime = field(default_factory=datetime.now)
    is_active: bool = True

# Uso
user = User(
    id="123",
    name="Alice",
    email="alice@example.com"
)

Data Classes con Validación

@dataclass
class User:
    email: str
    age: int

    def __post_init__(self):
        # Validar formato de email
        if "@" not in self.email:
            raise ValueError(f"Email inválido: {self.email}")
        # Validar rango de edad
        if self.age < 0 or self.age > 150:
            raise ValueError(f"Edad inválida: {self.age}")

Named Tuples

from typing import NamedTuple

class Point(NamedTuple):
    """Punto 2D inmutable."""
    x: float
    y: float

    def distance(self, other: 'Point') -> float:
        return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5

# Uso
p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance(p2))  # 5.0

Decoradores

Decoradores de Función

import functools
import time

def timer(func: Callable) -> Callable:
    """Decorador para medir el tiempo de ejecución de una función."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} tardó {elapsed:.4f}s")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(1)

# slow_function() imprime: slow_function tardó 1.0012s

Decoradores Parametrizados

def repeat(times: int):
    """Decorador para repetir una función múltiples veces."""
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(times):
                results.append(func(*args, **kwargs))
            return results
        return wrapper
    return decorator

@repeat(times=3)
def greet(name: str) -> str:
    return f"¡Hola, {name}!"

# greet("Alice") retorna ["¡Hola, Alice!", "¡Hola, Alice!", "¡Hola, Alice!"]

Decoradores Basados en Clases

class CountCalls:
    """Decorador que cuenta cuántas veces se llama una función."""
    def __init__(self, func: Callable):
        functools.update_wrapper(self, func)
        self.func = func
        self.count = 0

    def __call__(self, *args, **kwargs):
        self.count += 1
        print(f"{self.func.__name__} ha sido llamada {self.count} veces")
        return self.func(*args, **kwargs)

@CountCalls
def process():
    pass

# Cada llamada a process() imprime el conteo de llamadas

Patrones de Concurrencia

Threading para Tareas I/O-Bound

More skills from affaan-m/ECC

  • AaccessibilityWCAG 2.2 レベル AA 標準を用いてインクルーシブなデジタルプロダクトを設計・実装・監査します。Web 用のセマンティック ARIA および Web・ネイティブプラットフォーム(iOS/Android)のアクセシビリティトレイトを生成するために使用します。
  • Aagent-architecture-auditエージェントおよび LLM アプリケーション向けのフルスタック診断。12 層のエージェントスタックにおけるラッパーリグレッション、メモリ汚染、ツール規律の失敗、隠れた修復ループ、レンダリング破損を監査します。重要度順の発見事項とコードファーストの修正を生成します。エージェントアプリケーション、自律ループ、または LLM を活用した機能を構築する開発者に必須です。
  • Aagent-evalカスタムタスクでコーディングエージェント(Claude Code、Aider、Codex など)をヘッドツーヘッドで比較し、合格率、コスト、時間、一貫性のメトリクスを測定します
  • Aagent-harness-constructionAI エージェントのアクション空間、ツール定義、観測フォーマットを設計・最適化して完了率を向上させます。
  • Aagent-introspection-debuggingStructured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.
  • Aagent-introspection-debuggingキャプチャ、診断、封じ込め回復、内省レポートを使用した AI エージェント障害のための構造化された自己デバッグワークフロー。
  • Aagent-payment-x402タスクごとのバジェット、支出コントロール、ノンカストディアルウォレットを備えた x402 決済実行を AI エージェントに追加します。agentwallet-sdk を通じて Base をサポートし、OKX Payments / OKX エージェント決済プロトコルを通じて X Layer をサポートします。
  • Aagent-sortBuild an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.
  • Aagent-sort並行リポジトリ対応のレビューパスを使用して、スキル、コマンド、ルール、フック、エクストラを DAILY と LIBRARY のバケットに分類することで、特定のリポジトリ向けのエビデンスに基づいた ECC インストール計画を構築します。プロジェクトが完全なバンドルをロードする代わりに実際に必要なものに ECC をトリミングする必要がある場合に使用します。
  • Aagentic-engineeringOperate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when AI agents perform most implementation work and humans enforce quality and risk controls.
  • Aagentic-engineering評価ファースト実行、分解、コスト対応モデルルーティングを使用してエージェニックエンジニアとして動作します。
  • Aagentic-osClaude Code 上に永続的なマルチエージェントオペレーティングシステムを構築します。カーネルアーキテクチャ、スペシャリストエージェント、スラッシュコマンド、ファイルベースのメモリ、スケジュールされた自動化、外部データベースなしの状態管理をカバーします。

All agent skills → · MCP servers