Todo lo que debes conocer sobre Funciones en Python


Una función es un fragmento de código reutilizable cuya función es resolver un problema concreto que puede devolver o no un valor.

En Python las funciones siempre devuelven un valor (“none”), semejante al null de otros lenguajes como Javascript.

Las funciones ayudan a organizar el código, hacerlo más legible, entendible y por ende hacer más fácil el proceso de tracear (debugging). Siempre te será más sencillo revisar fragmentos separados de código, que un archivo grande sin división lógica entre las funciones que realiza.

Declaración e invocación de funciones en Python

En Python las funciones se declaran de la siguiente forma:

Ejemplo de función en Python.

Fig.1 Ejemplo de función en Python.

Como puedes observar, las funciones se declaran utilizando la palabra reservada def, algo que distingue a python de otros lenguajes como Java y C++.

Como vimos en la entrada anterior sobre este tema, los bloques de código comienzan con dos puntos y agrupan todo el código indentado a la derecha.

Las funciones se documentan incluyendo una cadena de texto luego de su declaración y antes de su contenido. Estas cadenas se conocen con el nombre de docstring (cadena de documentación).

Las cadenas de documentación, equivalentes a las anotaciones que se hacen en C# y Javadoc; tienen como objetivo documentar el código y permitir que herramientas de extracción de documentación puedan generar un manual sobre la API del programa que estemos creando. Ejemplo de estos programas con epydoc y doxygen.

Ejemplo de función documentada en Python.

Fig.2 Ejemplo de función documentada en Python.

Para invocar una función lo que hacemos es escribir su nombre seguido de paréntesis, entre los cuales se pasan los argumentos que requiera la misma. Por ejemplo, para ejecutar la función que vimos anteriormente escribimos:

my_function(5,4)

Paso de parámetros por nombre

Una función puede invocarse también definiendo manualmente qué valor darle a cada parámetro, a esta forma se le conoce como “paso de parámetros por nombre” y es útil cuando queremos pasar parámetros sin tener en cuenta el orden en que los espera una función. Por ejemplo, a la función anterior podríamos invocarla de la siguiente forma:

my_function(param2=5,param1=4)

Esto provoca que el parámetro 2 tome el valor 5, y no el parámetro 1, que es el que debería debido al orden en que están definidos. Esta forma de “paso de parámetros por nombre” puede ser combinada con el paso de parámetros posicional sin problemas.

Uso de parámetros por defecto

Si ejecutamos la función creada pasándole solo un parámetro, el intérprete de Python devuelve un mensaje como el siguiente:

Error que provoca ejecutar una función con un número incorrecto de parámetros en Python.

Fig.3 Error que provoca ejecutar una función con un número incorrecto de parámetros.

El intérprete nos informa de un error: la función my_function recibe dos parámetros y sólo se le está pasando uno.

En caso de que se deseara que el segundo parámetro tenga un valor definido por defecto, y por tanto no sea obligatorio pasárselo a la función cuando se invoca, se le debe asignar un valor por defecto en su declaración:

Definición de parámetros con un valor por defecto.

Fig.4 Definición de parámetros con un valor por defecto.

Ahora my_function puede ser llamada con solo el primer parámetro, si el segundo no es pasado se asume que es el especificado por defecto, el cual es asignado cuando se declara la función, por lo que los valores por defecto no deben ser mutables (listas, objetos complejos, diccionarios, etc.).

Parámetros excedentes *args, **kwargs

Python cuenta con un mecanismo que permite a las funciones manipular el exceso de parámetros, por ejemplo, si definimos una función como se muestra a continuación:

Ejemplo de función que acepta n parámetros en Python.

Fig.5 Ejemplo de función que acepta n parámetros.

El parámetro al que le precede un asterisco es una lista que contiene los parámetros pasados de forma posicional que no se encuentran en la definición de la función y el parámetro precedido por dos asteriscos, contendrá un diccionario con los parámetros excedentes pasados por nombre. Por ejemplo, si ejecutamos la función así:

example(1,2,3,uno=5,dos=9)

Obtendríamos la salida siguiente:

Salida que provoca la ejecución de la función anterior.

Fig.6 Salida que provoca la ejecución de la función anterior.

Paso de parámetros usando *args, **kwargs

Del mismo modo que se pueden capturar los parámetros excedentes (tanto los posicionales como los pasados por nombre) en las funciones se pueden invocar pasando, en vez de parámetros, iterables precedidos por * (en el caso de iterables) o ** (en el caso de los diccionarios). El comportamiento en ambos casos es el siguiente:

  • *iterable, la función recibe los elementos del iterable como parámetros posicionales.
  • **diccionario, cada par llave:valor será traducido en la llamada a la función como parámetro por nombre: llave=valor.

Para ver en la práctica cómo funciona esto hagamos uso de la función my_function definida más arriba y ejecutémosla de las siguientes formas:

Invocando una función pasándole un iterable.

Fig.7 Invocando una función pasándole un iterable.

En la figura anterior observas cómo pasar un iterable que sustituya los parámetros de una función, ahora te muestro cómo invocar la función pasándole un diccionario:

Invocando una función pasándole un diccionario.

Fig.8 Invocando una función pasándole un diccionario.

Retorno múltiple de valores

Una función en Python puede retornar múltiples valores usando tuplas. Esto se logra retornando varios valores separados por coma. A continuación un ejemplo tomado del modo interactivo:

Retornando varios valores en una función.

Fig.9 Retornando varios valores en una función.

Si deseamos capturar los valores retornados por una función podemos hacerlo de dos formas (ver Fig10).

Captura de varios valores retornados por una función.

Fig.10 Captura de varios valores retornados por una función.

Como puedes observar en la imagen anterior, si queremos podemos asignar los resultados a una variable y esta se convierte en una tupla, o podemos asignar los valores a variables individuales, poniéndolas dentro de paréntesis, formando una tupla con el mismo formato que devuelve la función.

Conclusiones

Como pudiste apreciar, Python brinda un gran abanico de opciones a la hora de trabajar con funciones.

Personalmente considero que su verdadero potencial radica en la flexibilidad que brinda a la hora de declararlas y devolver valores múltiples, característica esta que no está presente en todos los lenguajes.

¿Conoces algún otro uso de las funciones aparte de los mencionados en esta entrada? En caso positivo espero lo compartas en los comentarios. Con más, me despido y hasta un próximo encuentro. Happy Coding!!!