Convenções e Guia de Estilo
Idiomas Python acordados para a equipe - formatação, nomenclatura, tipagem, erros e commits - aplicados pelo ruff em CI e documentados aqui para que as revisões se concentrem no design, não no gosto.
Receita
from __future__ import annotations
from pathlib import Path
DATA_DIR = Path(__file__).resolve().parent / "data"
def load_config(path: Path) -> dict[str, str]:
try:
text = path.read_text(encoding="utf-8")
except OSError as exc:
raise ConfigError(f"não é possível ler {path}") from exc
return parse_env(text)Quando usar isso:
- Escrevendo novos módulos em serviços compartilhados
- Revisando PRs para consistência
- Integrando desenvolvedores de outras linguagens
- Resolvendo debates sobre "qual padrão usamos?"
Exemplo de Trabalho
# modules/billing/services/tax.py
from decimal import Decimal
from billing.domain.models import LineItem
from billing.settings import Settings
class TaxService:
def __init__(self, settings: Settings) -> None:
self._rate = Decimal(settings.vat_rate)
def compute(self, items: list[LineItem]) -> Decimal:
subtotal = sum((i.unit_price * i.quantity for i in items), start=Decimal("0"))
return (subtotal * self._rate).quantize(Decimal("0.01"))Mensagem de commit:
feat(billing): aplica IVA a itens de linha da UE [BILL-91]
Usa Decimal para matemática monetária. Adiciona teste de regressão para itens de quantidade zero.O que isso demonstra:
from __future__ import annotationspara referências futurasDecimalpara moeda - não float- Atributo privado
_rate; métodos públicos tipados - ID de ticket no assunto do commit
Mergulho Profundo
Como Funciona
- ruff - Substitui flake8, isort, pyupgrade; configuração em
pyproject.toml. - Comprimento da linha - Geralmente 88 ou 100 - a equipe escolhe um.
- Nomenclatura - PEP 8: funções
snake_case, classesPascalCase, constantesSCREAMING_SNAKE. - Importações - Regras do isort via ruff; sem
from module import *de wildcard.
Padrões da Equipe
| Tópico | Convenção |
|---|---|
| Strings | f-strings preferenciais |
| Caminhos | pathlib.Path em vez de os.path.join |
| Exceções | Tipos específicos; raise ... from exc |
| Logging | logging.getLogger(__name__) em vez de print |
| Async | Sem IO bloqueante em rotas async def |
| Dinheiro | Decimal ou centavos inteiros |
Notas Python
# trecho de pyproject.toml
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]
ignore = ["E501"] # se o formatador lida com o comprimento da linhaArmadilhas
- Versões de black/ruff por desenvolvedor - CI falha localmente, mas PR passou. Correção:
uv syncfixa as versões das ferramentas. - Type ignores sem ticket - A dívida se acumula. Correção:
# type: ignore[arg-type] # BILL-99. - Literais float para dinheiro - Bugs de
0.1 + 0.2. Correção: Decimal ou centavos inteiros. except:nu - Mascara KeyboardInterrupt. Correção: capturar no mínimoException, preferencialmente tipos específicos.- Atributos de classe mutáveis - Bugs de estado compartilhado. Correção: instâncias de dataclass ou atributos de instância.
- Padrões de framework inconsistentes - Globais do Flask no app FastAPI. Correção: seguir o ADR de serviço.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Documento de regras Python para toda a organização | Padrões entre equipes | Necessita de substituições específicas do serviço |
| Apenas ruff automatizado | Equipe pequena | Necessita de exemplos em texto para onboarding |
| Guia de estilo Python do Google | Referência externa | Conflitos com a configuração do ruff |
| Sem guia de estilo | Nunca | Revisões de detalhes sem fim |
FAQs
Black ou ruff format?
ruff format quando o ruff for adotado - uma ferramenta; não execute ambos.
Aspas simples ou duplas?
O formatador ruff escolhe consistentemente - não lute manualmente na revisão.
Dica de tipo para todas as variáveis locais?
API pública e locais não óbvias - não name = "ada" em funções pequenas.
Docstrings obrigatórias?
Módulos/classes/funções públicas sim - estilo Google ou numpy conforme README.
Comprimento máximo da linha 88 vs 100?
Escolha um em pyproject.toml - corresponda às expectativas do formatador e do revisor.
Imports relativos vs absolutos?
Absolutos from billing.domain import models em aplicativos - relativos apenas dentro de pacotes pequenos por ADR.
Enums vs literais?
StrEnum ou Literal para conjuntos pequenos e fechados - documentar na seção de type-hints.
Nomenclatura de testes?
test_<comportamento>_quando_<condição> - saída de falha legível.
Tipos de commit convencionais?
feat, fix, chore, docs, refactor, test - corresponder à automação de changelog, se houver.
Substituir convenção?
ADR ou comentário inline com motivo - não um único caso silencioso em um PR.
Relacionados
- PEP 8 e Referência de Estilo - referência
- 50 Regras Python - lista de regras
- Ruff e Formatadores - ferramentas
- Diretrizes de Revisão de Código - foco da revisão
Versões de Stack: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.