6.1.4 Documentación

6.1.4 Documentación

Ya hemos visto que en Python podemos incluir comentarios para explicar mejor determinadas zonas de nuestro código.

Del mismo modo podemos (y en muchos casos debemos) adjuntar documentación a la definición de una función incluyendo una cadena de texto (docstring) al comienzo de su cuerpo:

6.1.4 Documentación

La forma más ortodoxa de escribir un docstring es utilizando triples comillas:

6.1.4 Documentación

6.1.4 Documentación

Para ver el docstring de una función, basta con utilizar help:

6.1.4 Documentación

También es posible extraer información usando el símbolo de interrogación:

6.1.4 Documentación

Importante: Esto no sólo se aplica a funciones propias, sino a cualquier otra función definida en el lenguaje.

Nota: Si queremos ver el docstring de una función en «crudo» (sin formatear), podemos usar <function>._________________ doc__ .

Explicación de parámetros

Como ya se ha visto, es posible documentar una función utilizando un docstring. Pero la redacción y el formato de esta cadena de texto puede ser muy variada. Existen distintas formas de documentar una función (u otros objetos):

Sphinx docstrings Formato nativo de documentación Sphinx.

Google docstrings Formato de documentación recomendado por Google.

NumPy-SciPy docstrings Combinación de formatos reStructured y Google (usados por el proyecto NumPy).

Epytext Una adaptación a Python de Epydoc(Java).

Aunque cada uno tienes sus particularidades, todos comparten una misma estructura:

  • Una primera línea de descripción de la función.
  • A continuación especificamos las características de los parámetros (incluyendo sus tipos).
  • Por último, indicamos si la función retorna un valor y sus características.

Aunque todos los formatos son válidos, nos centraremos en Sphinx docstrings al ser el que viene mejor integrado con la documentación Sphinx. Google docstrings y Numpy docstrings también son ampliamente utilizados, lo único es que necesitan de un módulo externo denominado Napoleon para que se puedan incluir en la documentación Sphinx.

Sphinx

Sphinx es una herramienta para generar documentación e incluye un módulo «built-in» denominado autodoc el cual permite la autogeneración de documentación a partir de los «docstrings» definidos en el código.

Veamos el uso de este formato en la documentación de la siguiente función «dummy»:

6.1.4 Documentación

6.1.4 Documentación

Dentro del «docstring» podemos escribir con sintaxis reStructured Text – véase por ejemplo la expresión matemática en el tag :return: – lo que nos proporciona una gran flexibilidad.

Nota: La plataforma Read the Docs aloja la documentación de gran cantidad de proyectos. En muchos de los casos se han usado «docstrings» con el formato Sphinx visto anteriormente.

Anotación de tipos

Nivel intermedio

Las anotaciones de tipos se introdujeron en Python 3.5 y permiten indicar tipos para los parámetros de una función así como su valor de retorno (aunque también funcionan en creación de variables).

Veamos un ejemplo en el que creamos una función para dividir una cadena de texto por la posición especificada en el parámetro:

6.1.4 Documentación

Como se puede observar, vamos anadiendo los tipos después de cada parámetro utilizando : como separador. En el caso del valor de retorno usamos el símbolo ->

Quizás la siguiente ejecución pueda sorprender:

6.1.4 Documentación

Efectivamente como habrás visto, no hemos obtenido ningún error, a pesar de que estamos pasando como primer argumento una lista en vez de una cadena de texto. Esto ocurre porque lo que hemos definido es una anotación de tipo, no una declaración de tipo. Existen herramientas como mypy que sí se encargan de chequear estas situaciones.

Valores por defecto

Al igual que ocurre en la definición ordinaria de funciones, cuando usamos anotaciones de tipos también podemos indicar un valor por defecto para los parámetros.

Veamos la forma de hacerlo continuando con el ejemplo anterior:

6.1.4 Documentación

Simplemente añadimos el valor por defecto después de indicar el tipo.

Nota: Las anotaciones de tipos son una herramienta muy potente y que, usada de forma adecuada, permite complementar la documentación de nuestro código y aclarar ciertos aspectos, que a priori, pudieran parecer confusos. Su aplicación estará en función de la necesidad detectada por parte del equipo de desarrollo.
6.1.5 Tipos de funciones

Nivel avanzado

Funciones interiores

Está permitido definir una función dentro de otra función:

6.1.4 Documentación

6.1.4 Documentación

Clausuras

Una clausura (del término inglés «closure») establece el uso de una función interior que se genera dinámicamente y recuerda los valores de los argumentos con los que fue creada:

6.1.4 Documentación

Importante: En una clausura retornamos una función, no una llamada a la función.

Funciones anónimas «lambda»

Una función lambda tiene las siguientes propiedades:

  1. Se escribe con una única sentencia.
  2. No tiene nombre (anónima).
  3. Su cuerpo tiene implícito un return.
  4. Puede recibir cualquier número de parámetros.

Veamos un primer ejemplo de función «lambda» que nos permite contar el número de palabras de una cadena de texto:

6.1.4 Documentación

Veamos otro ejemplo en el que mostramos una tabla con el resultado de aplicar el «and» lógico mediante una función «lambda» que ahora recibe dos parámetros:

6.1.4 Documentación

Las funciones «lambda» son bastante utilizadas como argumentos a otras funciones. Un ejemplo claro de ello es la función sorted que tiene un parámetro opcional key donde se define la clave de ordenación.

Veamos cómo usar una función anónima «lambda» para ordenar una tupla de pares longitud -latitud:

6.1.4 Documentación

6.1.4 Documentación

Enfoque funcional

Como se comentó en la introducción, Python es un lenguaje de programación multiparadigma. Uno de los paradigmas menos explotados en este lenguaje es la programación funcional

Python nos ofrece 3 funciones que encajan verdaderamente bien en este enfoque: map(), filter() y reduce().

map()

Esta función aplica otra función sobre cada elemento de un iterable. Supongamos que queremos aplicar la siguiente función:

6.1.4 Documentación

6.1.4 Documentación

Figura 5: Rutinas muy enfocadas a programación funcional

6.1.4 Documentación

Aplicando una función anónima «lambda»…

6.1.4 Documentación

Importante: map() devuelve un generador, no directamente una lista.

filter()

Esta función selecciona aquellos elementos de un iterable que cumplan una determinada condición. Supongamos que queremos seleccionar sólo aquellos números impares dentro de un rango:

6.1.4 Documentación

6.1.4 Documentación

Aplicando una función anónima «lambda».

6.1.4 Documentación

Importante: filter() devuelve un generador, no directamente una lista.

reduce()

Para poder usar esta función debemos usar el módulo functools. Nos permite aplicar una función dada sobre todos los elementos de un iterable de manera acumulativa. O dicho en otras palabras, nos permite reducir una función sobre un conjunto de valores. Supongamos que queremos realizar el producto de una serie de valores aplicando este enfoque:

6.1.4 Documentación


Aplicando una
función anónima «lambda».

6.1.4 Documentación

Consejo: Por cuestiones de legibilidad del código, se suelen preferir las listas por comprensión a funciones como map() o filterQ, aunque cada problema tiene sus propias características y sus soluciones más adecuadas.

Publicaciones Similares