PEP 8 — Estilo Python sin sufrir, con `ruff` y `black

PEP 8 es la guía oficial de estilo de Python. La escribió Guido van Rossum (creador del lenguaje) en 2001 y desde entonces es el estándar que sigue cualquier proyecto serio. Si abres código Python ajeno y los nombres se leen igual, las indentaciones son consistentes, las líneas no se desbordan — eso es PEP 8 actuando.
¿Tienes que memorizarla? No. La buena noticia es que existen herramientas (ruff, black) que la aplican por ti automáticamente. Tú escribes el código como te apetece, das al guardar, y queda formateado al estándar. En esta entrada te enseño qué dice PEP 8 en lo que de verdad importa, y cómo configurar las dos herramientas que te dejan de quitar el sueño.
Contenido
- 1 Por qué te importa PEP 8
- 2 Lo importante de PEP 8 en 10 reglas
- 3 black — el formateador opinado
- 4 ruff — el linter ultrarrápido (y formateador moderno)
- 5 Configurar ruff en pyproject.toml
- 6 Integración con tu editor
- 7 Pre-commit: que no se te escape nada
- 8 Errores típicos al empezar
- 9 Resumen
- 10 Tu siguiente paso
Por qué te importa PEP 8
Tres motivos prácticos:
- Legibilidad cruzada. Cuando todo el mundo escribe igual, lees código ajeno sin esfuerzo. Tu yo del futuro y tus compañeros lo agradecen.
- Diff limpios en git. Si tú y otra persona usan formateadores distintos, cada commit cambia 100 líneas porque uno mete espacios y otro tabs. Con un formateador común, los diffs son solo lo que cambia de verdad.
- No discutir más. El formateo es una de esas conversaciones absurdas en code review (“dos espacios o cuatro”, “comilla simple o doble”). Con un formateador automático, se acabó: la herramienta decide y nadie debate.
Lo importante de PEP 8 en 10 reglas
No vas a memorizarlas, pero te las cuento para que cuando el linter te avise sepas de qué está hablando.
1. Indentación de 4 espacios. Nunca tabs.
def saludar(nombre):
return f"Hola, {nombre}" # ✓ 4 espacios
2. Líneas de máximo 79-88 caracteres. (PEP 8 dice 79; black puso de moda 88.)
mensaje = f"Hola {nombre}, gracias por suscribirte el {fecha} a las {hora}" # ← demasiado larga
3. Dos líneas en blanco entre funciones de top-level. Una entre métodos de clase.
def primera():
pass
def segunda(): # ← dos en blanco antes
pass
class Persona:
def __init__(self):
pass
def saludar(self): # ← una en blanco antes
pass
4. Imports al principio, agrupados: (1) stdlib, (2) terceros, (3) locales — separados por línea en blanco.
import json
import os
from pathlib import Path
import requests
from rich import print
from .modelos import Pelicula
from .utils import limpiar
5. Espacios alrededor de operadores y después de comas.
x = 5 + 3 # ✓
x=5+3 # ❌
mi_lista = [1, 2, 3] # ✓
mi_lista = [1,2,3] # ❌
6. Sin espacios dentro de paréntesis o llaves.
sumar(2, 3) # ✓
sumar( 2, 3 ) # ❌
7. Nombres descriptivos:
snake_casepara variables y funciones:nombre_completo,calcular_total.PascalCasepara clases:Pelicula,UsuarioAdmin.MAYUSCULAS_CON_GUION_BAJOpara constantes:MAX_INTENTOS = 3.- Variables privadas con un guion bajo:
_cache. Doble guion bajo solo si entiendes name mangling.
8. Comparación con None, True, False siempre con is:
if resultado is None: # ✓
if resultado == None: # ❌
if activo is True: # técnicamente válido, pero...
if activo: # ✓ más pythónico
9. Comillas: pick one and stick with it. PEP 8 no impone. La convención más común (y la que usa black) es comillas dobles ("hola"). Comillas simples ('hola') son válidas pero menos comunes.
10. Docstrings con triple comilla doble.
def calcular_total(precios):
"""Devuelve la suma de una lista de precios."""
return sum(precios)
💡 Esto es el 80% del PEP 8 práctico. La guía oficial tiene mucho más, pero con esto cubres lo que un linter te va a marcar el 95% del tiempo.
black — el formateador opinado
black es un formateador automático “sin opciones”. Eso es a propósito: tú no decides cómo se formatea, decide black. Y al ser sin opciones, es trivial de adoptar y consistente entre proyectos.
pip install black
# Formatear un fichero o carpeta
black mi_app.py
black src/
# Solo comprobar (sin modificar) — útil en CI
black --check src/
black corre, te reformatea el código y se acaba la discusión. Convierte comillas simples a dobles, ajusta saltos de línea, alinea argumentos largos, recorta espacios.
Antes:
def saludar(nombre,edad,ciudad='Madrid' ):
return 'Hola '+nombre+", "+str(edad)+' años, "+ciudad
Después de black:
def saludar(nombre, edad, ciudad="Madrid"):
return "Hola " + nombre + ", " + str(edad) + ' años, "' + ciudad
⚠️ Aviso:
blackmodifica los ficheros. Antes de pasarblacka un proyecto entero, asegúrate de que está bajo control de versiones. Si te pisas el commit te quedas sin código limpio antes/después.
📥 Llévate el cheatsheet de Python (gratis)
PDF de 6 páginas con lo esencial: tipos, condicionales, bucles, estructuras de datos, funciones y los errores que más vas a cometer. Para tener al lado mientras programas.
Sin spam. Te apuntas a la lista, descargas el cheatsheet y recibes contenido de Python cada semana.
ruff — el linter ultrarrápido (y formateador moderno)
ruff es un linter escrito en Rust que reemplaza a flake8, isort, pyflakes, pylint y un buen puñado de plugins. 10-100 veces más rápido que las alternativas de Python puro. Y desde hace poco también incluye formateador (ruff format) compatible con black.
pip install ruff
# Verificar el código
ruff check src/
# Formatear (compatible con black)
ruff format src/
# Auto-arreglar lo arreglable automáticamente
ruff check --fix src/
💡 Mi recomendación práctica: ruff sustituye black + flake8 + isort + más en una sola herramienta. Si empiezas un proyecto nuevo en 2026, ruff solo te basta.
Configurar ruff en pyproject.toml
pyproject.toml es el fichero estándar moderno para configurar herramientas Python. Mínimo razonable:
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "C4", "SIM"]
ignore = ["E501"] # line too long ya lo gestiona el formateador
[tool.ruff.format]
quote-style = "double"
Las reglas (select):
– E, W — errores y warnings de PEP 8 (de pycodestyle).
– F — fallos lógicos (de pyflakes): variables sin usar, imports sin usar.
– I — orden de imports (sustituye isort).
– N — nombres (snake_case, etc).
– UP — moderniza sintaxis (Optional[X] → X | None).
– B — flake8-bugbear: bugs comunes.
– C4 — comprehensions cleaner.
– SIM — simplificaciones de código.
Integración con tu editor
Casi cualquier IDE moderno tiene plugin para ruff/black que formatea al guardar. Dejas el editor configurado, escribes como te apetece, y al guardar queda perfecto sin pensar.
- PyCharm: plugin Ruff oficial. Settings → Tools → Actions on Save → activa “Reformat code” y “Run ruff”.
- VS Code: extensión “Ruff” de Astral. En
settings.jsonconfigura"editor.formatOnSave": truey"[python]": { "editor.defaultFormatter": "charliermarsh.ruff" }. - Vim/Neovim: integraciones con
null-ls,conform.nvim, etc.
💡 PyCharm es el IDE recomendado para empezar Python. Si vienes de otro mundo, te resultará casi tan productivo como un buen setup de VS Code, pero con muchísimas cosas pre-configuradas.
Pre-commit: que no se te escape nada
Para proyectos en equipo, una capa más: pre-commit. Hooks que se disparan antes de cada commit y verifican que el código está formateado.
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
pip install pre-commit
pre-commit install
A partir de aquí, cada git commit corre ruff sobre lo que vas a comitear. Si hay errores, no te deja commitear hasta que los arregles. Adiós a las code reviews con “le falta un punto y coma”.
Errores típicos al empezar
# 1. Usar tabs en vez de espacios — Python NO los mezcla
def f():
\tx = 1 # ❌ TabError si has mezclado tabs y espacios en el mismo bloque
# 2. CamelCase para funciones/variables (estilo Java)
def CalcularTotal(): # ❌ debe ser snake_case
def calcular_total(): # ✓
class movie: # ❌ las clases en PascalCase
class Movie: # ✓
# 3. Imports en medio del código (excepto casos justificados)
def cargar():
import json # ❌ pon el import arriba salvo razón fuerte
return json.loads(...)
# 4. Comparar con None usando ==
if x == None: # ❌ usa is
if x is None: # ✓
# 5. Pelearse con line-length sin formateador
mensaje = "Una línea increíblemente larga que ocupa toda la pantalla y rompe PEP 8"
# ❌ negociar con uno mismo es perder. Que black/ruff format decida.
Resumen
| Quieres… | Usa… |
|---|---|
| Una sola herramienta moderna | ruff (lint + format + isort) |
| Formateador opinado clásico | black |
| Configuración del proyecto | pyproject.toml |
| Integración en editor | Plugin Ruff/Black con format-on-save |
| Verificación pre-commit | pre-commit con hooks de ruff |
| Las reglas básicas | 4 espacios, 88 chars, snake_case, PascalCase, comillas dobles |
¿Te ha valido esto?
Si te ha resultado útil, llévate el cheatsheet de Python en PDF — 6 páginas con tipos, condicionales, bucles, estructuras de datos, funciones y los errores típicos. Para tener al lado mientras programas. Gratis.
Sin spam. Email + cheatsheet + un correo por semana con tutoriales nuevos.
Tu siguiente paso
Si has llegado hasta aquí, ya tienes el setup pro de estilo. Configuras ruff una vez, lo enchufas al editor con format-on-save, y nunca más vuelves a pensar en formato. Tu código se queda en PEP 8 por arte de magia y dedicas el cerebro a lo que importa: la lógica.
Si quieres aprender Python desde la base con buenas prácticas desde el primer día — estilo, módulos, tests, deploy — en El Pythonista lo enseño paso a paso.
Un abrazo,
Oscar
¿Quieres aprender Python en orden, no a saltos?
Esto que has leído es solo una pieza. En El Pythonista lo verás todo encadenado: 11 módulos, 37+ horas de vídeo, 734 actividades y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.
37+ horas · 734 actividades · Proyecto real · Acceso de por vida · 14 días de garantía
