Communitygithub.com

Padrões Python

Expressões idiomáticas Python, padrões PEP 8, dicas de tipo e melhores práticas para construir aplicações Python robustas, eficientes e sustentáveis. Use ao escrever ou revisar código Python e quando houver dúvidas sobre estrutura idiomática, tipagem ou PEP 8.

O que é Padrões Python?

Esta skill fornece um guia abrangente de padrões e melhores práticas de desenvolvimento Python, cobrindo desde princípios fundamentais como legibilidade e explicitabilidade até tópicos avançados como concorrência e organização de pacotes. Ela é ideal para desenvolvedores que escrevem, revisam ou refatoram código Python, ajudando a garantir que o código siga o estilo idiomático (PEP 8), utilize tipagem adequada (type hints), e empregue padrões de tratamento de erros (EAFP), context managers, decoradores, compreensões e geradores. A skill também aborda o uso de classes de dados, tuplas nomeadas, e otimizações de memória e desempenho com `__slots__` e geradores. É compatível com qualquer ambiente de desenvolvimento Python (IDEs, editores de código, ferramentas de IA) e seu conteúdo está estruturado em seções claras com exemplos de código que contrastam abordagens 'boas' e 'ruins', facilitando a consulta rápida durante o desenvolvimento.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/python-patterns

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Padrões de Desenvolvimento Python

Padrões Python idiomáticos e melhores práticas para construir aplicações robustas, eficientes e sustentáveis.

Quando Ativar

  • Escrevendo novo código Python
  • Revisando código Python
  • Refatorando código Python existente
  • Projetando pacotes/módulos Python

Princípios Fundamentais

1. Legibilidade é Importante

Python prioriza a legibilidade. O código deve ser óbvio e fácil de entender.

# Bom: Claro e legível
def get_active_users(users: list[User]) -> list[User]:
    """Retorna apenas usuários ativos da lista fornecida."""
    return [user for user in users if user.is_active]


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

2. Explícito é Melhor Que Implícito

Evite magia; seja claro sobre o que seu código faz.

# Bom: Configuração explícita
import logging

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

# Ruim: Efeitos colaterais ocultos
import some_module
some_module.setup()  # O que isso faz?

3. EAFP - É Mais Fácil Pedir Perdão do Que Permissão

Python prefere o tratamento de exceções em vez de verificar condições.

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

# Ruim: Estilo LBYL (Olhe Antes de Pular)
def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any:
    if key in dictionary:
        return dictionary[key]
    else:
        return default_value

Dicas de Tipo

Anotações 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]:
    """Processa um usuário e retorna o User atualizado ou None."""
    if not active:
        return None
    return User(user_id, data)

Dicas de Tipo Modernas (Python 3.9+)

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

# Python 3.8 e anteriores - Use o 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}

Aliases de Tipo e TypeVar

from typing import TypeVar, Union

# Alias de tipo para tipos complexos
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 o primeiro item ou None se a lista estiver vazia."""
    return items[0] if items else None

Duck Typing Baseado em Protocolo

from typing import Protocol

class Renderable(Protocol):
    def render(self) -> str:
        """Renderiza o objeto para uma string."""

def render_all(items: list[Renderable]) -> str:
    """Renderiza todos os itens que implementam o protocolo Renderable."""
    return "\n".join(item.render() for item in items)

Padrões de Tratamento de Erros

Tratamento de Exceções Específicas

# Bom: Captura exceções 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"Arquivo de configuração não encontrado: {path}") from e
    except json.JSONDecodeError as e:
        raise ConfigError(f"JSON inválido na configuração: {path}") from e

# Ruim: Except puro
def load_config(path: str) -> Config:
    try:
        with open(path) as f:
            return Config.from_json(f.read())
    except:
        return None  # Falha silenciosa!

Encadeamento de Exceções

def process_data(data: str) -> Result:
    try:
        parsed = json.loads(data)
    except json.JSONDecodeError as e:
        # Encadeia exceções para preservar o traceback
        raise ValueError(f"Falha ao analisar dados: {data}") from e

Hierarquia de Exceções Personalizada

class AppError(Exception):
    """Exceção base para todos os erros da aplicação."""
    pass

class ValidationError(AppError):
    """Levantada quando a validação de entrada falha."""
    pass

class NotFoundError(AppError):
    """Levantada quando um recurso solicitado não é encontrado."""
    pass

# Uso
def get_user(user_id: str) -> User:
    user = db.find_user(user_id)
    if not user:
        raise NotFoundError(f"Usuário não encontrado: {user_id}")
    return user

Gerenciadores de Contexto

Gerenciamento de Recursos

# Bom: Usando gerenciadores de contexto
def process_file(path: str) -> str:
    with open(path, 'r') as f:
        return f.read()

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

Gerenciadores de Contexto Personalizados

from contextlib import contextmanager

@contextmanager
def timer(name: str):
    """Gerenciador de contexto para medir o tempo de um bloco de código."""
    start = time.perf_counter()
    yield
    elapsed = time.perf_counter() - start
    print(f"{name} levou {elapsed:.4f} segundos")

# Uso
with timer("processamento de dados"):
    process_large_dataset()

Classes de Gerenciador de Contexto

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  # Não suprime exceções

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

Compreensões e Geradores

Compreensões de Lista

# Bom: Compreensão de lista para transformações simples
names = [user.name for user in users if user.is_active]

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

# Compreensões complexas devem ser expandidas
# Ruim: Muito complexo
result = [x * 2 for x in items if x > 0 if x % 2 == 0]

# Bom: Use uma função geradora
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

Expressões Geradoras

# Bom: Gerador para avaliação preguiçosa
total = sum(x * x for x in range(1_000_000))

# Ruim: Cria uma lista intermediária grande
total = sum([x * x for x in range(1_000_000)])

Funções Geradoras

def read_large_file(path: str) -> Iterator[str]:
    """Lê um arquivo grande linha por linha."""
    with open(path) as f:
        for line in f:
            yield line.strip()

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

Classes de Dados e Tuplas Nomeadas

Classes de Dados

from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class User:
    """Entidade User com __init__, __repr__ e __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="[email protected]"
)

Classes de Dados com Validação

@dataclass
class User:
    email: str
    age: int

    def __post_init__(self):
        # Valida formato do email
        if "@" not in self.email:
            raise ValueError(f"Email inválido: {self.email}")
        # Valida faixa etária
        if self.age < 0 or self.age > 150:
            raise ValueError(f"Idade inválida: {self.age}")

Tuplas Nomeadas

from typing import NamedTuple

class Point(NamedTuple):
    """Ponto 2D imutável."""
    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 Função

import functools
import time

def timer(func: Callable) -> Callable:
    """Decorador para medir o tempo de execução de uma função."""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        elapsed = time.perf_counter() - start
        print(f"{func.__name__} levou {elapsed:.4f}s")
        return result
    return wrapper

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

# slow_function() imprime: slow_function levou 1.0012s

Decoradores Parametrizados

def repeat(times: int):
    """Decorador para repetir uma função várias vezes."""
    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"Olá, {name}!"

# greet("Alice") retorna ["Olá, Alice!", "Olá, Alice!", "Olá, Alice!"]

Decoradores Baseados em Classe

class CountCalls:
    """Decorador que conta quantas vezes uma função é chamada."""
    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__} foi chamada {self.count} vezes")
        return self.func(*args, **kwargs)

@CountCalls
def process():
    pass

# Cada chamada a process() imprime a contagem de chamadas

Padrões de Concorrência

Threading para Tareas Ligadas a I/O

import concurrent.futures
import threading

def fetch_url(url: str) -> str:
    """Busca uma URL (operação ligada a I/O)."""
    import urllib.request
    with urllib.request.urlopen(url) as response:
        return response.read().decode()

def fetch_all_urls(urls: list[str]) -> dict[str, str]:
    """Busca múltiplas URLs concorrentemente usando threads."""
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        future_to_url = {executor.submit(fetch_url, url): url for url in urls}
        results = {}
        for future in concurrent.futures.as_completed(future_to_url):
            url = future_to_url[future]
            try:
                results[url] = future.result()
            except Exception as e:
                results[url] = f"Erro: {e}"
    return results

Multiprocessamento para Tarefas Ligadas a CPU

def process_data(data: list[int]) -> int:
    """Computação intensiva em CPU."""
    return sum(x ** 2 for x in data)

def process_all(datasets: list[list[int]]) -> list[int]:
    """Processa múltiplos datasets usando múltiplos processos."""
    with concurrent.futures.ProcessPoolExecutor() as executor:
        results = list(executor.map(process_data, datasets))
    return results

Async/Await para I/O Concorrente

import asyncio

async def fetch_async(url: str) -> str:
    """Busca uma URL assincronamente."""
    import aiohttp
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def fetch_all(urls: list[str]) -> dict[str, str]:
    """Busca múltiplas URLs concorrentemente."""
    tasks = [fetch_async(url) for url in urls]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(urls, results))

Organização de Pacotes

Estrutura Padrão de Projeto

myproject/
├── src/
│   └── mypackage/
│       ├── __init__.py
│       ├── main.py
│       ├── api/
│       │   ├── __init__.py
│       │   └── routes.py
│       ├── models/
│       │   ├── __init__.py
│       │   └── user.py
│       └── utils/
│           ├── __init__.py
│           └── helpers.py
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── test_api.py
│   └── test_models.py
├── pyproject.toml
├── README.md
└── .gitignore

Convenções de Importação

# Bom: Ordem de importação - stdlib, terceiros, locais
import os
import sys
from pathlib import Path

import requests
from fastapi import FastAPI

from mypackage.models import User
from mypackage.utils import format_name

# Bom: Use isort para ordenação automática de importações
# pip install isort

init.py para Exportações do Pacote

# mypackage/__init__.py
"""mypackage - Um pacote Python de exemplo."""

__version__ = "1.0.0"

# Exporta classes/funções principais no nível do pacote
from mypackage.models import User, Post
from mypackage.utils import format_name

__all__ = ["User", "Post", "format_name"]

Memória e Desempenho

Usando slots para Eficiência de Memória

# Ruim: Classe regular usa __dict__ (mais memória)
class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

# Bom: __slots__ reduz o uso de memória
class Point:
    __slots__ = ['x', 'y']

    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

Gerador para Grandes Dados

# Ruim: Retorna lista completa na memória
def read_lines(path: str) -> list[str]:
    with open(path) as f:
        return [line.strip() for line in f]

# Bom: Produz linhas uma de cada vez
def read_lines(path: str) -> Iterator[str]:
    with open(path) as f:
        for line in f:
            yield line.strip()

Evite Concatenação de Strings em Loops

# Ruim: O(n²) devido à imutabilidade de strings
result = ""
for item in items:
    result += str(item)

# Bom: O(n) usando join
result = "".join(str(item) for item in items)

# Bom: Usando StringIO para construção
from io import StringIO

buffer = StringIO()
for item in items:
    buffer.write(str(item))
result = buffer.getvalue()

Integração de Ferramentas Python

Comandos Essenciais

# Formatação de código
black .
isort .

# Linting
ruff check .

# Verificação de tipo
mypy src/

# Testes
pytest tests/
pytest --cov=src/ tests/

# Gerenciamento de dependências (recomendado)
# Usando pip-tools ou uv:
pip-compile pyproject.toml
pip-sync

# Usando Poetry:
poetry install
poetry add requests
poetry run pytest

Configuração de pyproject.toml

[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "myproject"
version = "1.0.0"
description = "Um projeto Python de exemplo"
requires-python = ">=3.9"
authors = [
    {name = "Seu Nome", email = "[email protected]"},
]
dependencies = [
    "requests>=2.28.0",
    "fastapi>=0.95.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.3.0",
    "black>=23.0",
    "isort>=5.12.0",
    "mypy>=1.3.0",
    "ruff>=0.1.0",
]

[tool.black]
line-length = 88
target-version = ["py39"]

[tool.isort]
profile = "black"

[tool.mypy]
python_version = "3.9"
warn_return_any = true
warn_unused_configs = true

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]

Referências

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured 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.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build 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.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Habilidades Relacionadas