2.5.-Documentar el código
2.5. Documentación del código en Python¶
Idea principal
Documentar no consiste en llenar el programa de comentarios. Consiste en hacer explícitos su propósito, su contrato y las decisiones que no pueden deducirse con seguridad leyendo solo las instrucciones.
Un programa se escribe una vez, pero se lee muchas veces: cuando se corrige un error, se añade una funcionalidad, se incorpora otra persona al equipo o se intenta reutilizar una biblioteca. Por eso la documentación forma parte de la calidad del software y no debe dejarse para el final.
En este tema distinguiremos comentar de documentar, aprenderemos a usar los comentarios y las docstrings de Python y veremos qué información debe acompañar a un proyecto. El recorrido empieza con la justificación y la motivación; después pasa a la escritura concreta de comentarios y documentación.
El tema se relaciona principalmente con el RA 3 del módulo de Programación:
| Código | Descripción literal de la normativa |
|---|---|
| RA 3 | Escribe y depura código, analizando y utilizando las estructuras de control del lenguaje. |
| CE 3.g | Se ha comentado y documentado el código. |
Se trabajan los criterios que tienen que ver con la documentación de código, incluyendo comentarios, docstrings y documentación de proyectos. La documentación debe ser clara, útil y mantenible, y debe explicar el propósito, el contrato y las decisiones del código.
Qué deberías saber al terminar
Al acabar este tema deberías poder:
- explicar por qué la documentación es parte de un software de calidad;
- distinguir comentarios, docstrings, anotaciones de tipo,
READMEy documentación de proyecto; - escribir comentarios breves que expliquen intención, decisiones y restricciones sin repetir el código;
- documentar módulos, funciones, clases, métodos y scripts con docstrings;
- elegir una convención de docstrings y mantenerla en todo el proyecto;
- preparar una documentación adecuada para proyectos privados, compartidos y públicos.
Mapa del tema
En este documento seguiremos esta progresión:
- justificación, motivación y audiencias de la documentación;
- comentarios útiles frente a comentarios redundantes;
- docstrings, tipos de objetos y formatos de documentación en Python;
- documentación de proyectos, herramientas, buenas prácticas y práctica.
1. Por qué debemos documentar el código¶
1.1. El código se lee más veces de las que se escribe¶
Guido van Rossum, creador de Python, resumió una realidad cotidiana del desarrollo:
“Code is more often read than written.”
—Guido van Rossum
Cuando escribes código te diriges, al menos, a dos audiencias:
- las personas que utilizarán el programa o la biblioteca;
- las personas que mantendrán el código, incluida tu versión futura.
Es normal que, meses después, no recuerdes por qué una variable tenía un valor concreto, por qué se eligió un algoritmo o qué supuesto hacía válida una condición. Si a ti te cuesta reconstruir la decisión, a otra persona del equipo le costará aún más.
Una biblioteca sin documentación
Imagina que encuentras una biblioteca que parece resolver exactamente tu problema. Sin ejemplos, explicación de parámetros ni documentación oficial, tendrás que estudiar toda su implementación para saber cómo usarla. Es posible que decidas no utilizarla, aunque te ahorrase mucho trabajo.
Daniele Procida expresa esta idea de forma directa:
“It doesn’t matter how good your software is, because if the documentation is not good enough, people will not use it.”
1.2. Un sistema sin documentación está incompleto¶
Un sistema de calidad debe comunicar, como mínimo:
- por qué existen sus módulos, clases y funciones;
- qué problema resuelve cada parte;
- cómo se utiliza;
- qué datos acepta y qué resultado produce;
- qué efectos secundarios, restricciones o errores pueden aparecer.
Sin esta información, modificar un sistema existente se convierte en una investigación costosa. Para usar una función sin documentación hay que leer su implementación y deducir su comportamiento; para mantenerla, además, hay que adivinar qué pretendía hacer quien la escribió.
La documentación debe estar lo más cerca posible del código al que se refiere. Un comentario, una docstring o un ejemplo versionado junto al código es más fácil de encontrar y actualizar que un documento perdido en una carpeta de la nube. Para la documentación de usuario o de un proyecto completo también puede existir un sitio especializado, como MkDocs, Sphinx, Read the Docs o Docusaurus, pero esos sistemas deben construirse a partir de información controlada y mantenida.
Puedes documentar, entre otras cosas:
- decisiones de diseño;
- la razón de existir y el funcionamiento de una parte no evidente;
- las interfaces públicas y ejemplos de uso;
- los efectos de utilizar una función o módulo;
- limitaciones conocidas, código pendiente y mejoras posibles mediante
TODOoFIXMEcon contexto.
Documentación
La documentación es la información que explica el propósito, el uso, el contrato, las decisiones y las restricciones de un software para que otras personas puedan utilizarlo, mantenerlo o ampliarlo.
1.3. Documentar ayuda a diseñar¶
John Ousterhout, en A Philosophy of Software Design, propone utilizar los comentarios también como herramienta de diseño. Antes de implementar una función o módulo, explicar en lenguaje natural su propósito, interfaz y efectos permite comprobar si el diseño es lógico y suficiente.
Esta técnica es especialmente útil para la interfaz: obliga a ponerse en el lugar de quien utilizará el código. Si no puedes escribir una descripción corta y concreta de cómo se usa una pieza o por qué existe, quizá debas replantear su diseño antes de programarla.
flowchart TD
A["Necesidad del programa"] --> B["Explicar propósito e interfaz"]
B --> C{"¿El diseño se entiende?"}
C -->|"No"| D["Revisar responsabilidades y uso"]
D --> B
C -->|"Sí"| E["Implementar código claro"]
E --> F["Añadir comentarios y docstrings útiles"]
F --> G["Publicar README y documentación del proyecto"]
Los comentarios no sustituyen al diseño, pero escribirlos pronto puede revelar una interfaz confusa antes de invertir tiempo en una implementación difícil de mantener.
1.4. El lenguaje de programación no expresa todas las decisiones¶
Python permite expresar con precisión el comportamiento ejecutable, pero no resulta práctico codificar todas las razones, restricciones y decisiones del equipo. El código suele explicar cómo se realiza una operación; la documentación puede explicar por qué se realiza de esa forma.
No es un fracaso necesitar una explicación en lenguaje natural. Es una decisión correcta cuando el comentario aporta una información que el código no puede expresar de forma clara y razonable. Lo que debemos evitar es usar comentarios como sustituto habitual de nombres, funciones y estructuras comprensibles.
2. Comentar no es lo mismo que documentar¶
Ambos conceptos están relacionados, pero no tienen exactamente el mismo objetivo:
| Elemento | Audiencia principal | Qué explica | Dónde aparece |
|---|---|---|---|
| Comentario | Personas que leen y mantienen el código | Intención, decisión, algoritmo o limitación local | Junto a una instrucción o bloque |
| Docstring | Personas que usan o mantienen una API | Contrato, parámetros, retorno, excepciones y ejemplos | En módulos, clases, funciones y métodos |
README |
Personas que llegan al proyecto | Propósito, instalación y uso inicial | Raíz del repositorio |
| Guía o referencia | Personas usuarias o desarrolladoras | Procedimientos, conceptos y API completa | Carpeta o sitio de documentación |
Jeff Atwood lo resume así:
“Code tells you how; Comments tell you why.”
Aclaración
La frontera no es absoluta: una docstring también puede servir a una
persona desarrolladora y un README puede incluir información técnica. Lo
importante es identificar a quién va dirigida la información y colocarla
donde esa persona la buscará.
2.1. Comentarios con #¶
En Python, un comentario comienza con # y el intérprete no ejecuta el texto
que aparece después en esa línea:
def hello_world():
# Explica la intención de la salida para quien lee el ejemplo.
print("Hello World")
También puede aparecer al final de una instrucción, aunque conviene reservar los comentarios en línea para aclaraciones muy breves:
PEP 8 recomienda limitar las líneas de código a 79 caracteres y las líneas de comentarios o docstrings a 72 cuando se trata de texto con menos restricciones estructurales. No es una regla del intérprete, sino una convención que facilita leer diferencias, editores y terminales. Si una explicación es larga, divídela en varias líneas:
def hello_long_world():
# La salida es deliberadamente larga porque se usa para probar
# el ajuste de línea del terminal, no porque sea un saludo habitual.
print("Hellooooooooooooooooooooooooooooooooooooooooooooooooooooooo World")
2.2. Para qué puede servir un comentario¶
Los comentarios pueden cumplir funciones distintas:
-
Planificación y revisión: permiten anotar pasos antes de implementar una funcionalidad. Deben eliminarse o transformarse en documentación definitiva después de revisar y probar el código.
Una práctica especialmente útil consiste en escribir primero la explicación de la interfaz: propósito, forma de uso, efectos y restricciones. Esto permite detectar un diseño confuso antes de programarlo. No significa que todo comentario deba escribirse antes del código, sino que la documentación también puede ser una herramienta de diseño y revisión.
-
Intención de un bloque: explica una decisión que no resulta obvia al leer las instrucciones.
-
Descripción algorítmica: resume la estrategia, su complejidad o el motivo de elegir un algoritmo cuando esos datos son relevantes.
-
Etiquetado de trabajo pendiente:
TODO,FIXMEoBUGayudan a localizar problemas conocidos. Deben incluir una descripción concreta y no convertirse en una lista de promesas olvidadas.
2.3. Escribe comentarios que aporten información¶
La regla práctica es: comenta el porqué, no repitas el qué.
# Redundante: el código ya expresa la operación.
x = x + 1 # Incrementar x en 1
# Útil: explica una decisión externa al código.
x = x + 1 # Compensar el índice basado en 1 de la API heredada.
# Redundante: el nombre y el literal son suficientes.
usuarios = [] # Crear una lista vacía
# Útil: explica el motivo de conservar la colección.
usuarios = [] # Caché para evitar consultas repetidas durante la sesión.
Antes de añadir un comentario sobre la implementación, pregúntate si puedes
mejorar el código: cambia x por un nombre descriptivo, extrae una función o
divide una expresión compleja. Si después de esa mejora sigue siendo necesaria
la explicación, escríbela de forma breve y cercana al código.
Las decisiones cambian
Un comentario incorrecto o desactualizado puede ser peor que no tenerlo.
Cada vez que cambies el comportamiento de un bloque, revisa también los
comentarios, las docstrings, los ejemplos y el README relacionado.
2.4. Cuatro reglas para comentarios mantenibles¶
Estas reglas, difundidas por Jeff Atwood, son una guía práctica:
- Mantén el comentario cerca del código que describe. Una explicación alejada se pasa por alto y se desincroniza con facilidad.
- Evita formatos complejos, como tablas de caracteres o dibujos ASCII. Suelen distraer y son difíciles de mantener.
- No incluyas información redundante. Supón que quien lee conoce la sintaxis básica de Python y explica solo lo que no puede deducir con seguridad.
- Diseña el código para que sea legible por sí mismo: nombres expresivos, funciones pequeñas y estructuras claras reducen la necesidad de comentarios.
2.5. Las anotaciones de tipo también comunican¶
Las anotaciones de tipo, disponibles desde Python 3.5, hacen más explícito el contrato de una función:
Al leer la cabecera se entiende que name se espera como texto y que la
función devuelve texto. En Python moderno también pueden anotarse colecciones:
def procesar_nombres(nombres: list[str]) -> int:
return len(nombres)
def obtener_configuracion() -> dict[str, int]:
return {"timeout": 30, "reintentos": 3}
Las anotaciones son información accesible, por ejemplo, mediante
funcion.__annotations__, pero Python no las valida automáticamente en cada
llamada ni garantiza que el valor cumpla el tipo. Herramientas como
mypy o
Pyright pueden analizarlas. Por tanto,
los type hints complementan las docstrings y la validación explícita; no
las sustituyen.
2.6. Las cadenas triples no son comentarios¶
Una cadena entre triples comillas ("""...""" o '''...''') es un literal de
cadena. Se convierte en docstring únicamente cuando es la primera instrucción
de un módulo, una clase o una función. Una cadena suelta en cualquier otro lugar
no es un comentario y no debe usarse como sustituto habitual de #:
def sumar(a: int, b: int) -> int:
"""Devuelve la suma de dos enteros.""" # Esta sí es una docstring.
return a + b
# Para una anotación temporal o local, usa un comentario real.
resultado = sumar(2, 3) # Se conserva para mostrar el ejemplo.
Las triples comillas son la convención de Python para docstrings porque permiten escribir texto de una o varias líneas. No significa que toda cadena triple sea documentación ni que una cadena independiente sea ignorada como un comentario.
3. Docstrings: documentación integrada en Python¶
3.1. Qué es una docstring¶
Una docstring es una cadena de documentación asociada automáticamente al
primer literal de cadena del cuerpo de un módulo, una clase, una función o un
método. Python la
expone mediante el atributo __doc__, y la función help() la muestra en la
consola. Las herramientas de documentación pueden leerla para generar una
referencia de API.
def say_hello(name: str) -> None:
"""Imprime un saludo personalizado."""
print(f"Hello {name}, is it me you're looking for?")
print(say_hello.__doc__)
help(say_hello)
La docstring debe estar inmediatamente después de la cabecera del objeto que
documenta. Python también permite asignar manualmente __doc__ en objetos
definidos por el programa, aunque escribirla en su posición natural es más
legible:
def say_hello(name: str) -> None:
print(f"Hello {name}, is it me you're looking for?")
say_hello.__doc__ = "Imprime un saludo personalizado."
Los objetos integrados pueden impedir esa asignación:
>>> str.__doc__ = "Una nueva documentación para str"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot set '__doc__' attribute of immutable type 'str'
También puedes consultar la documentación de objetos incorporados:
>>> dir(str)
['__add__', ..., '__doc__', ..., 'zfill']
>>> print(str.__doc__)
str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str
...
3.2. Convenciones de PEP 257¶
PEP 257 establece convenciones para que las docstrings sean reconocibles y consistentes. No obliga a describir cada línea interna ni impone un formato completo para parámetros, pero sí recomienda que sean concisas, útiles y fáciles de mantener.
Para una docstring de una sola línea, escribe un resumen completo en una línea, normalmente con triples comillas dobles:
Una docstring más extensa puede seguir este patrón:
def calcular_area_rectangulo(ancho: float, alto: float) -> float:
"""Calcula el área de un rectángulo.
La unidad del resultado es el cuadrado de la unidad recibida.
"""
return ancho * alto
La primera línea resume el comportamiento; una línea en blanco separa el resumen de la ampliación. Las líneas de texto deberían respetar la recomendación de 72 caracteres de PEP 8 cuando sea razonable.
Una docstring de una interfaz pública suele describir:
- qué hace y para qué sirve;
- qué significan sus argumentos, incluidos los opcionales y sus valores por defecto;
- qué devuelve y en qué condiciones;
- qué excepciones puede producir;
- qué efectos secundarios tiene;
- qué restricciones o precondiciones deben cumplirse;
- ejemplos de uso si aclaran el contrato.
3.3. Docstrings de funciones y métodos¶
Este ejemplo usa el formato Google Style, sencillo y adecuado para empezar:
def calcular_promedio(numeros: list[float]) -> float:
"""Calcula el promedio de una lista de números.
Args:
numeros: Lista de números que se va a promediar.
Returns:
El promedio de los valores recibidos.
Raises:
ValueError: Si la lista está vacía.
"""
if not numeros:
raise ValueError("La lista no puede estar vacía.")
return sum(numeros) / len(numeros)
La función comunica su contrato sin obligar a leer la implementación. Si una función tiene un efecto secundario, como escribir un fichero o modificar una colección recibida, debe indicarlo expresamente.
3.4. Docstrings de clases y métodos¶
La docstring de una clase resume qué representa, su comportamiento y sus
atributos públicos. Cada método público puede tener su propia docstring. Los
parámetros del constructor se documentan en __init__ o en la docstring de la
clase, siguiendo la convención elegida para el proyecto.
class Animal:
"""Representa un animal y el sonido que puede emitir.
Attributes:
name: Nombre del animal.
sound: Sonido utilizado por defecto.
num_legs: Número de patas; por defecto es 4.
"""
says_template = "{name} dice {sound}"
def __init__(self, name: str, sound: str | None, num_legs: int = 4) -> None:
"""Inicializa un animal.
Args:
name: Nombre del animal.
sound: Sonido por defecto; puede ser `None`.
num_legs: Número de patas, que por defecto es 4.
"""
self.name = name
self.sound = sound
self.num_legs = num_legs
def says(self, sound: str | None = None) -> None:
"""Muestra el nombre y el sonido del animal.
Args:
sound: Sonido alternativo. Si se omite, se usa el predeterminado.
Raises:
NotImplementedError: Si no existe ningún sonido disponible.
"""
if self.sound is None and sound is None:
raise NotImplementedError("No se admiten animales silenciosos.")
out_sound = self.sound if sound is None else sound
print(self.says_template.format(name=self.name, sound=out_sound))
En una clase más grande también conviene documentar la interfaz prevista para subclases, las propiedades que deben mantenerse coherentes y los métodos que pueden sobrescribirse.
3.5. Docstrings de módulos y paquetes¶
La docstring de un módulo se coloca al principio del archivo, antes de los
import. Debe explicar el propósito del módulo y puede enumerar las clases,
excepciones y funciones principales que ofrece:
"""Utilidades geométricas para figuras planas.
El módulo ofrece `Rectangulo`, `Circulo` y funciones de cálculo de áreas.
"""
import math
La docstring de un paquete se coloca al principio de __init__.py. Puede
explicar qué proporciona el paquete y qué submódulos o nombres forman parte de
su interfaz pública. La documentación de cada función del módulo debe incluir
los mismos elementos que la de un método: propósito, argumentos, retorno,
efectos, excepciones y restricciones.
3.6. Docstrings de scripts ejecutables¶
Un script ejecutado desde la consola debe explicar qué hace, cómo se invoca,
qué argumentos acepta y qué dependencias necesita. Si utiliza argparse, esa
información puede integrarse en la descripción y en la ayuda de cada argumento:
"""Muestra las columnas de una hoja de cálculo.
Admite ficheros CSV y Excel (`.xls`, `.xlsx`). Requiere instalar `pandas`.
"""
import argparse
def main() -> None:
"""Procesa los argumentos y muestra las columnas solicitadas."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input_file", help="Fichero de hoja de cálculo")
args = parser.parse_args()
print(f"Procesando {args.input_file}")
if __name__ == "__main__":
main()
La condición if __name__ == "__main__" permite importar el módulo sin
ejecutar el programa automáticamente. Las dependencias propias o de terceros,
como pandas, deben aparecer en la documentación de instalación y en los
ficheros de dependencias del proyecto.
3.7. Un script completo con una biblioteca externa¶
El siguiente ejemplo conserva el caso de una utilidad para obtener cabeceras de hojas de cálculo. La docstring del módulo explica el uso del script y la de la función documenta sus parámetros y retorno:
"""Imprime las cabeceras de una hoja de cálculo.
Admite ficheros CSV y Excel (`.xls`, `.xlsx`). Requiere `pandas`.
También puede importarse como módulo; ofrece `get_spreadsheet_cols` y `main`.
"""
import argparse
from pathlib import Path
import pandas as pd
def get_spreadsheet_cols(file_loc: str, print_cols: bool = False) -> list[str]:
"""Obtiene y, opcionalmente, muestra las cabeceras de una hoja.
Args:
file_loc: Ruta del fichero de hoja de cálculo.
print_cols: Si es `True`, muestra las cabeceras en la consola.
Returns:
Lista de nombres de columna.
Raises:
ValueError: Si la extensión no es `.csv`, `.xls` o `.xlsx`.
"""
extension = Path(file_loc).suffix.lower()
if extension == ".csv":
file_data = pd.read_csv(file_loc)
elif extension in {".xls", ".xlsx"}:
file_data = pd.read_excel(file_loc)
else:
raise ValueError("El fichero debe ser CSV o Excel.")
col_headers = list(file_data.columns)
if print_cols:
print("\n".join(col_headers))
return col_headers
def main() -> None:
"""Lee la ruta de la línea de órdenes y muestra sus columnas."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input_file", help="Fichero cuyas columnas se mostrarán")
args = parser.parse_args()
get_spreadsheet_cols(args.input_file, print_cols=True)
if __name__ == "__main__":
main()
4. Formatos y documentación de proyectos Python¶
4.1. Elegir un formato de docstring¶
No existe un único formato obligatorio para describir parámetros y retornos. Lo importante es elegir uno que entiendan las herramientas del proyecto y aplicarlo de forma coherente. Estos son formatos habituales:
| Formato | Características | Soporte habitual |
|---|---|---|
| Google Style | Sintaxis Args, Returns y Raises, fácil de leer. |
Sphinx mediante extensiones y otras herramientas. |
| reStructuredText | Formato muy integrado con el ecosistema de Sphinx. | Sphinx y Docutils. |
| NumPy/SciPy | Secciones con títulos como Parameters y Returns. |
NumPyDoc y Sphinx. |
| Epytext | Adaptación usada por Epydoc. | Epydoc y herramientas compatibles. |
Los ejemplos siguientes documentan la misma función con estilos distintos:
4.1.1. Google Style¶
"""Obtiene las cabeceras de una hoja de cálculo.
Args:
file_loc (str): Ruta del fichero.
print_cols (bool): Si muestra las cabeceras en consola.
Returns:
list[str]: Nombres de las columnas.
"""
4.1.2. Texto reestructurado¶
"""Obtiene las cabeceras de una hoja de cálculo.
:param file_loc: Ruta del fichero.
:type file_loc: str
:param print_cols: Si muestra las cabeceras en consola.
:type print_cols: bool
:returns: Nombres de las columnas.
:rtype: list[str]
"""
4.1.3. NumPy/SciPy¶
"""Obtiene las cabeceras de una hoja de cálculo.
Parameters
----------
file_loc : str
Ruta del fichero.
print_cols : bool, optional
Si muestra las cabeceras en consola.
Returns
-------
list[str]
Nombres de las columnas.
"""
4.1.4. Epytext¶
"""Obtiene las cabeceras de una hoja de cálculo.
@type file_loc: str
@param file_loc: Ruta del fichero.
@type print_cols: bool
@param print_cols: Si muestra las cabeceras en consola.
@rtype: list[str]
@returns: Nombres de las columnas.
"""
4.2. Estructura orientativa de un proyecto¶
La documentación depende del tamaño, del tipo de usuarios y del nivel de colaboración. Una raíz de proyecto puede organizarse así:
project_root/
├── project/ # Código fuente del paquete
├── tests/ # Pruebas automatizadas
├── docs/ # Tutoriales, guías y referencia
├── README.md # Primer contacto con el proyecto
├── HOW_TO_CONTRIBUTE.md # Cómo colaborar
├── CODE_OF_CONDUCT.md # Normas de convivencia
├── LICENSE # Licencia
└── examples.py # Ejemplos sencillos de uso
No todos los proyectos necesitan todos estos ficheros. El principio práctico es documentar lo que otra persona necesita para instalar, utilizar, mantener o contribuir al proyecto.
4.2.1. Proyectos privados¶
Un proyecto privado puede necesitar una documentación ligera:
README.md: propósito, requisitos y forma de instalación o ejecución;examples.pyo una carpetaexamples/: usos sencillos;- comentarios y docstrings para decisiones que puedan resultar confusas en el futuro.
Aunque solo lo utilices tú, también eres una persona usuaria. Tu versión futura agradecerá saber qué necesita instalar y qué supuestos utiliza el programa.
4.2.2. Proyectos compartidos¶
Cuando colaboran varias personas, conviene añadir:
- cambios importantes entre versiones;
- instrucciones para empezar a contribuir;
- convenciones de código, pruebas y revisión;
- ejemplos que permitan comprobar rápidamente la instalación.
El objetivo es reducir el tiempo de incorporación y evitar que cada persona tenga que descubrir las reglas del proyecto leyendo todo su código.
4.2.3. Proyectos públicos y de código abierto¶
Un proyecto público debe conceder a la documentación una prioridad semejante a
la del desarrollo. El README.md suele incluir propósito, requisitos,
instalación, uso, ejemplos, cambios importantes, enlaces a la documentación,
forma de informar de errores y licencia. Además, suelen ser necesarios:
- Contribución: cómo proponer cambios, pruebas o documentación;
- código de conducta: comportamiento esperado en la comunidad;
- licencia: condiciones para utilizar y redistribuir el software;
docs/: documentación ampliada organizada por necesidades.
4.2.4. Un README.md mínimo¶
# Mi proyecto
Descripción breve del problema que resuelve.
## Instalación
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## Uso
```python
from mi_proyecto import funcion_principal
resultado = funcion_principal()
print(resultado)
```
## Contribuir
1. Crea una rama.
2. Añade código y pruebas.
3. Comprueba el formato y ejecuta la suite.
4. Abre una solicitud de cambios.
## Licencia
MIT
4.3. Las cuatro necesidades de docs/¶
Daniele Procida propone separar la documentación de un proyecto en cuatro tipos. No son cuatro niveles de calidad, sino cuatro formas de ayudar a la persona lectora:
- Tutoriales: guían paso a paso a quien está aprendiendo.
- Guías prácticas: resuelven una tarea concreta mediante una receta.
- Referencias: ofrecen información precisa para consultar mientras se programa, como una API o una tabla de opciones.
- Explicaciones: ayudan a comprender conceptos, arquitectura y decisiones.
| Tipo de contenido | Más útil al estudiar | Más útil al programar |
|---|---|---|
| Paso práctico | Tutoriales | Guías prácticas |
| Conocimientos teóricos | Explicaciones | Referencias |
Separar estos objetivos evita que un tutorial para principiantes se convierta en una lista de detalles de API o que una referencia técnica obligue a seguir una secuencia didáctica innecesaria.
4.4. Herramientas y recursos¶
| Herramienta | Uso principal |
|---|---|
| Sphinx | Generar documentación a partir de fuentes y docstrings. |
| Epydoc | Generar referencia de API Python a partir de docstrings. |
| Read the Docs | Crear, versionar y alojar documentación automáticamente. |
| Doxygen | Generar documentación para varios lenguajes, incluido Python. |
| MkDocs | Crear sitios estáticos con Markdown; este repositorio utiliza MkDocs Material. |
| Pycco | Mostrar código y documentación uno junto a otro. |
pydoc |
Consultar o generar documentación de módulos Python. |
| Docusaurus | Construir sitios de documentación, especialmente en el ecosistema JavaScript. |
También es útil estudiar proyectos bien documentados, como Django, Requests, Click y Pandas.
4.5. Recursos para profundizar¶
Los siguientes recursos amplían las ideas del tema y conservan referencias útiles del material original:
- Consejos para empezar con Python.
- Guía de PyCon.
- Cómo empezar a contribuir a un proyecto Python.
- Comentarios en programación.
- When Good Comments Go Bad, de Jeff Atwood.
- Interfaces en Python.
- Constructores de clases en Python.
- Métodos de instancia, clase y estáticos.
- Comparativa de analizadores de línea de órdenes.
- Diseño de la estructura de una aplicación Python.
- Cómo escribir un buen
README. - Cómo añadir un código de conducta a un proyecto.
- Documentación de proyectos Python con MkDocs.
- Generación de documentación con Pycco.
- Charla de PyCon 2017 sobre documentación.
- Práctica de Sphinx de Carol Willing.
- Desarrollo basado en documentación, de Daniele Procida.
- Documentación con Sphinx y Read the Docs, de Eric Holscher.
- Construir, probar y documentar un proyecto Python.
- Documentación básica de reStructuredText.
- Código fuente de la documentación de Django.
- Código fuente de la documentación de Requests.
- Código fuente de la documentación de Click.
- Código fuente de la documentación de Pandas.
4.6. Cómo empezar si el proyecto no tiene documentación¶
La documentación de un proyecto suele evolucionar en esta progresión:
- Sin documentación.
- Alguna documentación.
- Documentación completa.
- Buena documentación.
- Gran documentación.
No es necesario resolverlo todo de una vez. Si no existe ningún documento,
empieza por un README.md con el propósito, los requisitos y un ejemplo de
ejecución. Después añade las docstrings de la interfaz pública, guías para
tareas frecuentes y referencia técnica. La constancia es más útil que intentar
escribir una enciclopedia que nadie pueda mantener.
5. Buenas prácticas¶
Para trabajar con documentación con criterio profesional, conviene aplicar estas pautas:
- Empieza por la interfaz: escribe cómo se usa, por qué existe y qué efectos produce antes de describir detalles internos.
- Explica el porqué: documenta decisiones, restricciones, algoritmos no obvios y soluciones temporales; el código ya expresa normalmente qué hace.
- Escribe código legible: usa nombres descriptivos, funciones pequeñas y estructuras sencillas para que el programa se explique a sí mismo.
- Documenta la interfaz pública: incluye parámetros, retorno, excepciones, efectos secundarios, restricciones y ejemplos cuando aporten valor.
- Elige una convención: Google, reStructuredText, NumPy/SciPy y Epytext son opciones válidas si las herramientas del proyecto las soportan; no las mezcles sin una razón clara.
- Mantén la documentación cerca y actualizada: trata comentarios,
docstrings,
READMEy guías como parte del código revisado. - Automatiza cuando compense: integra linters, comprobadores de tipos,
doctest, pruebas y generadores de documentación en el flujo del proyecto. - Adapta el esfuerzo al contexto: un script privado no necesita la misma documentación que una biblioteca pública, pero sí debe dejar claras sus dependencias y decisiones difíciles de recordar.
- Protege la información sensible: no incluyas contraseñas, tokens ni datos personales en comentarios, ejemplos, capturas o documentación publicada.
6. Errores frecuentes¶
| Error frecuente | Por qué ocurre | Cómo evitarlo |
|---|---|---|
| Comentar cada línea obvia. | Se confunde documentar con traducir el código a lenguaje natural. | Usa nombres claros y comenta solo la intención no evidente. |
Usar cadenas con """ como si fueran comentarios. |
Se olvida que una cadena suelta es una expresión y solo ciertas posiciones crean docstrings. | Usa # para comentarios y reserva las triples comillas para docstrings. |
| Documentar solo el nombre de una función. | Se describe que existe, pero no su contrato. | Explica parámetros, retorno, excepciones, efectos y restricciones. |
| Colocar mal una docstring. | Solo el primer literal de un módulo, clase o función se convierte automáticamente en __doc__. |
Colócala inmediatamente después de la cabecera correspondiente. |
| Afirmar que un type hint valida el valor. | Python no comprueba automáticamente las anotaciones en cada llamada. | Valida explícitamente y usa mypy o Pyright si es necesario. |
| Mezclar formatos de docstring. | Cada persona usa nombres y secciones diferentes. | Elige un formato y aplícalo en todo el proyecto. |
Dejar TODO o FIXME sin contexto. |
La etiqueta queda olvidada y no indica qué debe hacerse. | Escribe una acción concreta y enlaza una incidencia cuando proceda. |
| Mantener documentación desactualizada. | Se trata como una tarea posterior al cambio de código. | Revísala en cada cambio relevante y en la revisión de código. |
| Crear documentación aislada del código. | El documento se pierde o deja de coincidir con la implementación. | Versiona la documentación técnica junto al código y publica la de usuario con el proyecto. |
| Usar un formato correcto, pero no documentar el contrato. | Se presta más atención a la sintaxis que a la información que necesita quien usa la API. | Comprueba siempre propósito, entradas, salida, errores, efectos y ejemplos. |
7. Resumen¶
En este tema has aprendido que:
- la documentación es parte de la calidad del software y sirve a personas usuarias, desarrolladoras y a tu yo futuro;
- un comentario debe explicar sobre todo decisiones e intención, mientras que una docstring describe el contrato de un módulo, una clase o una función;
- Python utiliza
#para comentarios y reconoce como docstrings los literales colocados en posiciones concretas; help(),__doc__,pydoc, Sphinx y MkDocs permiten consultar o publicar documentación;- los type hints complementan las docstrings, pero no sustituyen la validación ni garantizan por sí solos el tipo de los valores;
- la documentación debe estar cerca del código, seguir una convención y actualizarse junto con la implementación.
Idea clave
Un buen comentario o una buena docstring aporta información que el código no expresa por sí solo: el propósito, el contrato, los efectos y las decisiones que hacen comprensible y mantenible el programa.
Conclusión¶
Documentar es una habilidad de programación, no una tarea decorativa. Empieza
por hacer el código claro, añade comentarios solo cuando aporten contexto,
describe las interfaces públicas con docstrings y acompaña el proyecto con un
README y unas guías ajustadas a sus personas usuarias. Así, el trabajo será
más fácil de utilizar, revisar, depurar y ampliar.
8. Para seguir practicando¶
- Añade comentarios que expliquen decisiones no evidentes a uno de los programas de la práctica de documentación del código y elimina los que repitan literalmente el código.
- Documenta con docstrings una función de conversión, otra de validación y
una clase; comprueba después
__doc__conprint()yhelp(). - Elige Google Style o NumPy Style y reescribe con él las docstrings de un pequeño módulo, incluyendo parámetros, retorno, excepciones y ejemplos.
- Crea un
README.mdmínimo con instalación, uso y ejemplos para uno de tus programas. - Revisa la depuración de programas y relaciona los comentarios de diseño con las hipótesis que se comprueban al depurar.
Bibliografía y fuentes¶
- PEP 8: guía de estilo para código Python.
- PEP 257: convenciones para docstrings.
- Documentación oficial de Python:
pydoc. - Documentación oficial de Python: anotaciones de funciones.
- Real Python: Documenting Python Code.
- Héctor Patricio: ¿Deberías documentar tu código?.
- Jeff Atwood: Code tells you how; Comments tell you why.
- Daniele Procida: Documentation system.
- John Ousterhout, A Philosophy of Software Design.
- Normativa oficial del título de Desarrollo de Aplicaciones Web.
Presentación¶
Puedes repasar los conceptos principales con la presentación de documentación del código.