Fundamentos de la Programación

#09 – Funciones (II)

Aunque ya sabemos todo lo que hay que saber sobre las funciones (o no :P), en esta entrada vamos a tratar un caso especial de funciones. Se trata de las funciones recursivas.

Recursividad

Ya sabemos crear funciones. Desde esta funciones, podemos llamar a otras funciones, lo que nos da un poder de cálculo enorme. Pero, ¿y si desde una función llamamos a la misma función? De eso se tratan las funciones recursivas: funciones que se llaman a si mismas. Aunque pueda parecer algo difícil de entender, con un ejemplo en seguida quedará claro.

Factorial de un Número

Matemáticamente, el factorial de un número se define con la siguiente función:

¿Hay algo que os llame la atención? Cuando el número a calcular el factorial es distinto de cero, el factorial del mismo es ese número multiplicado por el factorial del número anterior. Es decir, que para calcular el factorial de un número necesitamos el factorial del anterior. ¿Veis la recursividad? Calculemos el factorial de 5:

5!
5 · 4!
5 · 4 · 3!
5 · 4 · 3 · 2!
5 · 4 · 3 · 2 · 1
!
5 · 4 · 3 · 2 · 1 · 0!
5 · 4 · 3 · 2 · 1
120

Ahora, escribamos la función anterior mediante código de Python. ¿Veis las similitudes?

def factorial(n):
	if n == 0:
		return 1
	elif n > 0:
		return factorial(n - 1) * n

Cuando escribimos funciones recursivas tenemos que tener mucho cuidado con definir bien la condición de parada (el caso donde se dejará de llamar a la función recursivamente). En este ejemplo, se trata de cuando el número a calcular el factorial es 0 (podríamos poner 0 o 1, ya que ambos tienen el mismo valor, con lo que nos ahorraríamos una iteración, pero se ha dejado así por la similitud con la fórmula). Si no lo hacemos bien, podríamos entrar en un bucle infinito y, en caso extremo, agotar los recursos de la máquina.

¿Recursividad o Bucle?

En los ejercicios ya hemos visto el cálculo del factorial de un número, utilizando para ello un bucle. Entonces, ¿qué debemos usar, el bucle o la recursividad? Debéis de saber que para toda función recursiva, siempre existe otra que realiza el mismo calculo con un bucle. El problema es que no siempre es fácil encontrar dicha función, y la versión recursiva suele ser más elegante, al parecerse más a la definición matemática. No obstante, la versión con bucle suele ser más eficiente. Quedará al criterio y habilidad del programador el decantarse por una u otra.

Recursión Indirecta

Existe un modo especial de recursión: la recursión indirecta. Se trata de cuando una función llama a otra función distinta, y esta es la que llama de nuevo a la primera función. El bucle de llamadas se ha completado gracias a elementos intermedios.

Importación de Módulos

Hemos visto como el uso de funciones nos ayuda a no repetir código en nuestros programas, teniendo que escribirlo sólo una vez. Sin embargo, ahora se da el caso de que usamos la misma función en varios programas. ¿Tenemos que escribirla cada vez que hagamos un nuevo programa? Por suerte, la respuesta es no. Python dispone de los llamados módulos, que son colecciones de funciones que el programador puede utilizar sin tener que escribirlas.

Existen una gran cantidad de módulos predefinidos, como el módulo math que se uso en la entrega anterior para añadir a nuestro programa la función de cálculo de la raíz cuadrada sqrt(). Los módulos resultan muy importantes, ya que resuelven problemas que se le pueden plantear al programador, y no vamos a estar reinventando la rueda en cada programa que hagamos, si ya lo han hecho otros antes por nosotros.

Generando Módulos

A continuación vamos a generar un pequeño módulo que nos sirva para calcular el menor o el mayor de dos números. La función para calcular el número menor será:

def min(a, b):
	if a < b:
		return a
	else:
		return b

De manera análoga, la función para calcular el número mayor será:

def max(a, b):
	if a > b:
		return a
	else:
		return b

Ahora debemos guardar el fichero que hemos escrito. En este caso de ejemplo, lo haremos bajo el nombre de minmax.py. Ya hemos creado nuestro módulo. ¿Cómo lo usamos? Utilizando import al principio del programa. Debemos especificar desde dónde importamos (fijaos que se ha eliminado la extensión .py) y las funciones a importar.

from minmax import min, max

print(min(1,5))
print(max(1,5))

Para agilizar las pruebas, y no tener que realizarlas desde otro programa, los módulos suelen llevar una sección de código que sólo se ejecutará cuando sea el propio fichero del módulo el que se esté ejecutando, y no al realizar llamadas desde otros programas. Para ello, utilizamos una variable especial, __name__, que nos permite saber si se trata del programa principal o no. Nuestro módulo minmax.py quedará de la siguiente manera:

def min(a, b):
	if a < b:
		return a
	else:
		return b
		
def max(a, b):
	if a > b:
		return a
	else:
		return b
		
if __name__ == '__main__':
	print("El máximo de 1 y 5 es: "+str(max(1,5)))
	print("El máximo de 1 y -5 es: "+str(max(1,-5)))
	print("El mínimo de 1 y 5 es: "+str(min(1,5)))
	print("El mínimo de 1 y -5 es: "+str(min(1,-5)))

Módulos en OnlineGDB

Utilizar nuestros propios módulos en OnlineGDB resulta más sencillo de lo que podríamos pensar al principio. Básicamente, en lugar de guardar el módulo para después importarlo, lo que debemos hacer es tenerlo cargado en el intérprete. Veamoslo paso a paso:

  • En primer lugar, nuestro programa principal debe estar escrito en la pestaña main.py.
  • Para crear el nuevo módulo, utilizamos el botón de nuevo archivo.
  • Este nuevo archivo deberá de llevar puesto el nombre con el que habríamos guardado nuestro módulo. En este caso, minmax.py.
  • Finalmente, en la pestaña que se ha creado, escribimos nuestro módulo.

Con esto, nuestro módulo está listo para ser utilizado.


Con esta entrega finalizamos todo lo relacionado con las funciones. A estas alturas, somos capaces de crear programas muy interesantes. Uno de ellos es el ejercicio 11, donde generaremos la solución de un popular rompecabezas.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

back to top