¿Qué es PEP 8?
PEP 8 es la guía de estilo oficial para código Python. Define convenciones sobre cómo formatear código para hacerlo más legible y consistente. Seguir PEP 8 es fundamental para escribir código profesional que otros desarrolladores puedan entender fácilmente.
¿Por Qué es Importante?
- Legibilidad: Código más fácil de leer y entender
- Mantenimiento: Facilita actualizaciones y correcciones
- Colaboración: Estándar común en equipos
- Profesionalismo: Demuestra conocimiento de mejores prácticas
- Comunidad: Código consistente con proyectos open source
Indentación
Regla Principal: 4 Espacios
# Correcto
def mi_funcion():
if True:
print("Hola")
# Incorrecto - 2 espacios
def mi_funcion():
if True:
print("Hola")
# Incorrecto - tabs
def mi_funcion():
if True:
print("Hola")Continuación de Línea
# Correcto - alineado con delimitador de apertura
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Correcto - indentación extra para distinguir
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Correcto - hanging indent
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# Incorrecto - argumentos en primera línea sin indentación
foo = long_function_name(var_one, var_two,
var_three, var_four)Longitud de Línea
Máximo 79 Caracteres
# Correcto - menos de 79 caracteres
def mi_funcion(parametro1, parametro2):
return parametro1 + parametro2
# Correcto - dividir líneas largas
resultado = mi_funcion_con_nombre_largo(
parametro_uno,
parametro_dos,
parametro_tres
)
# Correcto - usar paréntesis para dividir
texto = (
"Esta es una línea muy larga que necesita "
"ser dividida en múltiples líneas para "
"mantener la legibilidad del código"
)Líneas en Blanco
# Dos líneas en blanco antes de definiciones de clase
class MiClase:
pass
class OtraClase:
pass
# Dos líneas en blanco antes de funciones de nivel superior
def funcion_principal():
pass
def otra_funcion():
pass
# Una línea en blanco entre métodos
class MiClase:
def metodo_uno(self):
pass
def metodo_dos(self):
passImports
Orden de Imports
# 1. Biblioteca estándar
import os
import sys
from datetime import datetime
# 2. Bibliotecas de terceros
import requests
import pandas as pd
from flask import Flask
# 3. Imports locales
from mi_modulo import mi_funcion
from .otro_modulo import OtraClaseFormato de Imports
# Correcto - imports en líneas separadas
import os
import sys
# Correcto - múltiples items de un módulo
from subprocess import Popen, PIPE
# Incorrecto
import os, sys
# Correcto - imports absolutos preferidos
from mipaquete.subpaquete import modulo
# Aceptable - imports relativos explícitos
from . import modulo_hermano
from ..paquete_padre import otro_moduloEspacios en Blanco
Evitar Espacios Innecesarios
# Correcto
spam(ham[1], {eggs: 2})
# Incorrecto
spam( ham[ 1 ], { eggs: 2 } )
# Correcto
foo = (0,)
# Incorrecto
bar = (0, )
# Correcto
if x == 4:
print(x, y)
x, y = y, x
# Incorrecto
if x == 4 :
print(x , y)
x , y = y , xOperadores
# Correcto - un espacio alrededor de operadores
x = 1
y = 2
resultado = x + y
# Correcto - sin espacios en prioridad alta
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
# Correcto - asignación en argumentos
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# Incorrecto
x=1
y=2
resultado=x+yConvenciones de Nombres
Variables y Funciones - snake_case
# Correcto
mi_variable = 10
nombre_completo = "Ana García"
def calcular_promedio(numeros):
return sum(numeros) / len(numeros)
# Incorrecto
miVariable = 10 # camelCase
NombreCompleto = "Ana" # PascalCase
def CalcularPromedio(numeros): # PascalCase
passClases - PascalCase
# Correcto
class MiClase:
pass
class UsuarioAdministrador:
pass
# Incorrecto
class mi_clase: # snake_case
pass
class usuarioAdministrador: # camelCase
passConstantes - UPPER_CASE
# Correcto
MAX_OVERFLOW = 100
TOTAL_ITEMS = 50
PI = 3.14159
# Incorrecto
max_overflow = 100
MaxOverflow = 100Métodos y Variables Privadas - _prefijo
class MiClase:
def __init__(self):
self.publico = "visible"
self._privado = "interno" # Convención de privado
self.__muy_privado = "name mangling" # Name mangling
def metodo_publico(self):
return self._metodo_privado()
def _metodo_privado(self):
return "interno"Comentarios
Comentarios de Línea
# Correcto - comentario sobre el código
x = x + 1 # Incrementar x
# Correcto - comentario de bloque
# Este es un comentario más largo que explica
# algo complejo que necesita múltiples líneas
# para ser completamente claro.
if x > 0:
print("Positivo")
# Incorrecto - comentario obvio
x = x + 1 # sumar uno a xDocstrings
def mi_funcion(parametro1, parametro2):
"""
Breve descripción de la función.
Descripción más detallada si es necesario.
Puede tener múltiples párrafos.
Args:
parametro1 (int): Descripción del parámetro 1
parametro2 (str): Descripción del parámetro 2
Returns:
bool: Descripción del valor de retorno
Raises:
ValueError: Cuándo se lanza esta excepción
Examples:
>>> mi_funcion(5, "test")
True
"""
return True
class MiClase:
"""
Breve descripción de la clase.
Descripción más detallada de qué hace la clase
y cómo usarla.
Attributes:
atributo1 (int): Descripción del atributo
atributo2 (str): Descripción del atributo
"""
def __init__(self, valor):
"""Inicializar la clase con un valor."""
self.valor = valorComparaciones
# Correcto - usar 'is' para None
if x is None:
pass
# Incorrecto
if x == None:
pass
# Correcto - comparar con True/False
if greeting:
pass
# Incorrecto
if greeting == True:
pass
# Correcto - verificar listas vacías
if not seq:
pass
# Incorrecto
if len(seq) == 0:
passExpresiones y Sentencias
Múltiples Sentencias
# Correcto
if foo == 'blah':
do_blah_thing()
do_one()
do_two()
# Incorrecto - múltiples sentencias en una línea
if foo == 'blah': do_blah_thing()
do_one(); do_two()Comprensiones
# Correcto - simple y legible
result = [x for x in range(10) if x % 2 == 0]
# Correcto - dividir si es muy largo
result = [
x * 2
for x in range(10)
if x % 2 == 0
if x > 5
]
# Incorrecto - demasiado complejo
result = [x if x > 0 else -x if x < -10 else 0 for x in range(-20, 20) if x != 0]Ejemplo de Código Completo PEP 8
"""
Módulo de ejemplo siguiendo PEP 8.
Este módulo demuestra las convenciones de estilo
de Python según PEP 8.
"""
import os
import sys
from datetime import datetime
import requests
from flask import Flask
# Constantes
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30
class UserManager:
"""
Gestiona operaciones de usuarios.
Esta clase proporciona métodos para crear, actualizar
y eliminar usuarios del sistema.
Attributes:
users (list): Lista de usuarios activos
max_users (int): Número máximo de usuarios permitidos
"""
def __init__(self, max_users=100):
"""Inicializar el gestor de usuarios."""
self.users = []
self.max_users = max_users
self._last_update = None
def add_user(self, username, email):
"""
Agregar un nuevo usuario.
Args:
username (str): Nombre de usuario único
email (str): Dirección de email del usuario
Returns:
bool: True si se agregó exitosamente, False en caso contrario
Raises:
ValueError: Si el username ya existe
"""
if self._user_exists(username):
raise ValueError(f"Usuario {username} ya existe")
if len(self.users) >= self.max_users:
return False
user = {
'username': username,
'email': email,
'created_at': datetime.now()
}
self.users.append(user)
self._last_update = datetime.now()
return True
def _user_exists(self, username):
"""Verificar si un usuario existe (método privado)."""
return any(user['username'] == username for user in self.users)
def get_user_count(self):
"""Obtener el número total de usuarios."""
return len(self.users)
def calculate_average(numbers):
"""
Calcular el promedio de una lista de números.
Args:
numbers (list): Lista de números
Returns:
float: Promedio de los números
Raises:
ValueError: Si la lista está vacía
"""
if not numbers:
raise ValueError("La lista no puede estar vacía")
return sum(numbers) / len(numbers)
def main():
"""Función principal del programa."""
# Crear gestor de usuarios
manager = UserManager(max_users=50)
# Agregar usuarios
try:
manager.add_user('ana', 'ana@email.com')
manager.add_user('luis', 'luis@email.com')
print(f"Total usuarios: {manager.get_user_count()}")
except ValueError as e:
print(f"Error: {e}")
# Calcular promedio
numbers = [10, 20, 30, 40, 50]
average = calculate_average(numbers)
print(f"Promedio: {average}")
if __name__ == '__main__':
main()Herramientas para Verificar PEP 8
pycodestyle (antes pep8)
# Instalar
pip install pycodestyle
# Verificar archivo
pycodestyle mi_script.py
# Ver estadísticas
pycodestyle --statistics mi_script.pyflake8
# Instalar
pip install flake8
# Verificar
flake8 mi_script.py
# Configurar en setup.cfg
[flake8]
max-line-length = 88
exclude = .git,__pycache__,venvblack - Auto-formateador
# Instalar
pip install black
# Formatear archivo
black mi_script.py
# Ver cambios sin aplicar
black --check mi_script.py
# Formatear todo el proyecto
black .autopep8
# Instalar
pip install autopep8
# Formatear archivo
autopep8 --in-place --aggressive mi_script.pyConfiguración en Editores
VS Code (settings.json)
{
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"editor.rulers": [79, 120]
}PyCharm
Settings → Editor → Code Style → Python → Configurar según PEP 8
Excepciones a las Reglas
PEP 8 reconoce que a veces es necesario romper las reglas:
- Cuando seguir la regla haría el código menos legible
- Para ser consistente con código circundante
- En código legacy que no sigue PEP 8
- Cuando el código necesita ser compatible con versiones antiguas
Resumen de Convenciones
- ✅ Indentación: 4 espacios
- ✅ Línea máxima: 79 caracteres
- ✅ Funciones/variables: snake_case
- ✅ Clases: PascalCase
- ✅ Constantes: UPPER_CASE
- ✅ Privados: _prefijo
- ✅ Imports: ordenados y agrupados
- ✅ Docstrings: en funciones y clases
- ✅ Espacios: alrededor de operadores
- ✅ Comparaciones: usar 'is' para None
Conclusión
Seguir PEP 8 es esencial para escribir código Python profesional. Aunque puede parecer restrictivo al principio, estas convenciones mejoran significativamente la legibilidad y mantenibilidad del código. Usa herramientas automáticas como black o flake8 para facilitar el cumplimiento de estas reglas. Recuerda: el código se lee mucho más de lo que se escribe.