Link Search Menu Expand Document

Funciones en Python

Anteriormente hemos usado funciones nativas que vienen con Python como len() para calcular la longitud de una lista, pero al igual que en otros lenguajes de programaci贸n, tambi茅n podemos definir nuestras propias funciones. Para ello hacemos uso de def.

def nombre_funcion(argumentos):
    c贸digo
    return retorno

Cualquier funci贸n tendr谩 un nombre, unos argumentos de entrada, un c贸digo a ejecutar y unos par谩metros de salida. Al igual que las funciones matem谩ticas, en programaci贸n nos permiten realizar diferentes operaciones con la entrada, para entregar una determinada salida que depender谩 del c贸digo que escribamos dentro. Por lo tanto, es totalmente an谩logo al cl谩sico y=f(x) de las matem谩ticas.

def f(x):
    return 2*x
y = f(3)
print(y) # 6

Algo que diferencia en cierto modo las funciones en el mundo de la programaci贸n, es que no s贸lo realizan una operaci贸n con sus entradas, sino que tambi茅n parten de los siguientes principios:

  • El principio de reusabilidad, que nos dice que si por ejemplo tenemos un fragmento de c贸digo usado en muchos sitios, la mejor soluci贸n ser铆a pasarlo a una funci贸n. Esto nos evitar铆a tener c贸digo repetido, y que modificarlo fuera m谩s f谩cil, ya que bastar铆a con cambiar la funci贸n una vez.
  • Y el principio de modularidad, que defiende que en vez de escribir largos trozos de c贸digo, es mejor crear m贸dulos o funciones que agrupen ciertos fragmentos de c贸digo en funcionalidades espec铆ficas, haciendo que el c贸digo resultante sea m谩s f谩cil de leer.

Pasando argumentos de entrada

Empecemos por la funci贸n m谩s sencilla de todas. Una funci贸n sin par谩metros de entrada ni par谩metros de salida.

def di_hola():
    print("Hola")

Hemos declarado o definido la funci贸n. El siguiente paso es llamarla con di_hola(). Si lo realizamos veremos que se imprime Hola.

di_hola() # Hola

Vamos a complicar un poco las cosas pasando un argumento de entrada. Ahora si pasamos como entrada un nombre, se imprimir谩 Hola y el nombre.

def di_hola(nombre):
    print("Hola", nombre)
di_hola("Juan")
# Hola Juan

Python permite pasar argumentos tambi茅n de otras formas. A continuaci贸n las explicamos todas.

Argumentos por posici贸n

Los argumentos por posici贸n o posicionales son la forma m谩s b谩sica e intuitiva de pasar par谩metros. Si tenemos una funci贸n resta() que acepta dos par谩metros, se puede llamar como se muestra a continuaci贸n.

def resta(a, b):
    return a-b
resta(5, 3) # 2

Al tratarse de par谩metros posicionales, se interpretar谩 que el primer n煤mero es la a y el segundo la b. El n煤mero de par谩metros es fijo, por lo que si intentamos llamar a la funci贸n con solo uno, dar谩 error.

#resta(1) # Error! TypeError

Tampoco es posible usar mas argumentos de los tiene la funci贸n definidos, ya que no sabr铆a que hacer con ellos. Por lo tanto si lo intentamos, Python nos dir谩 que toma 2 posicionales y estamos pasando 3, lo que no es posible.

#TypeError: resta() takes 2 positional arguments but 3 were given
#resta(5,4,3) # Error

Argumentos por nombre

Otra forma de llamar a una funci贸n, es usando el nombre del argumento con = y su valor. El siguiente c贸digo hace lo mismo que el c贸digo anterior, con la diferencia de que los argumentos no son posicionales.

resta(a=3, b=5) # -2

Al indicar en la llamada a la funci贸n el nombre de la variable y el valor, el orden ya no importa, y se podr铆a llamar de la siguiente forma.

resta(b=5, a=3) # -2

Como es de esperar, si indicamos un argumento que no ha sido definido como par谩metro de entrada, tendremos un error.

#resta() got an unexpected keyword argument 'c'
#resta(b=5, c=3) # Error!

Argumentos por defecto

Tal vez queramos tener una funci贸n con alg煤n par谩metro opcional, que pueda ser usado o no dependiendo de diferentes circunstancias. Para ello, lo que podemos hacer es asignar un valor por defecto a la funci贸n. En el siguiente caso c valdr铆a cero salvo que se indique lo contrario.

def suma(a, b, c=0):
    return a+b+c
suma(5,5,3) # 13

Dado que el par谩metro c tiene un valor por defecto, la funci贸n puede ser llamada sin ese valor.

suma(4,3) # 7

Podemos incluso asignar un valor por defecto a todos los par谩metros, por lo que se podr铆a llamar a la funci贸n sin ning煤n argumento de entrada.

def suma(a=3, b=5, c=0):
    return a+b+c
suma() # 8

Las siguientes llamadas a la funci贸n tambi茅n son v谩lidas

suma(1)     # 6
suma(4,5)   # 9
suma(5,3,2) # 10

O haciendo uso de lo que hemos visto antes y usando los nombres de los argumentos.

suma(a=5, b=3) #8

Argumentos de longitud variable

En el ejemplo con argumentos por defecto, hemos visto que la funci贸n puede ser llamada con diferente n煤mero de argumentos de entrada, pero esto no es realmente una funci贸n con argumentos de longitud variable, ya que existe un n煤mero m谩ximo.

Imaginemos que queremos una funci贸n suma() como la de antes, pero en este caso necesitamos que sume todos los n煤meros de entrada que se le pasen, sin importar si son 3 o 100. Una primera forma de hacerlo ser铆a con una lista.

def suma(numeros):
    total = 0
    for n in numeros:
        total += n
    return total
suma([1,3,5,4]) # 13

La forma es v谩lida y cumple nuestro requisito, pero realmente no estamos trabajando con argumentos de longitud variable. En realidad tenemos un solo argumento que es una lista de n煤meros.

Por suerte, Python tiene una herramienta muy potente. Si declaramos un argumento con *, esto har谩 que el argumento que se pase sea empaquetado en una tupla de manera autom谩tica. No confundir * con los punteros en otros lenguajes de programaci贸n, no tiene nada que ver.

def suma(*numeros):
    print(type(numeros))
    # <class 'tuple'>
    total = 0
    for n in numeros:
        total += n
    return total
suma(1, 3, 5, 4) # 13

El resultado es igual que el anterior, y podemos ver como efectivamente numeros es de la clase tuple. Tambi茅n podemos hacer otras llamadas con diferente n煤mero de argumentos

suma(6) # 6
suma(6, 4, 10) # 20
suma(6, 4, 10, 20, 4, 6, 7) # 57

Usando doble ** es posible tambi茅n tener como par谩metro de entrada una lista de elementos almacenados en forma de clave y valor. En este caso podemos iterar los valores haciendo uso de items().

def suma(**kwargs):
    suma = 0;
    for key, value in kwargs.items():
        print(key, value)
        suma += value
    return suma

suma(a=5, b=20, c=23) # 48

De igual manera, podemos pasar un diccionario como par谩metro de entrada.

def suma(**kwargs):
    suma = 0
    for key, value in kwargs.items():
        print(key, value)
        suma += value
    return suma
di = {'a': 10, 'b':20}
suma(**di) # 30

Sentencia return

El uso de la sentencia return permite realizar dos cosas:

  • Salir de la funci贸n y transferir la ejecuci贸n de vuelta a donde se realiz贸 la llamada.
  • Devolver uno o varios par谩metros, fruto de la ejecuci贸n de la funci贸n.

En lo relativo a lo primero, una vez se llama a return se para la ejecuci贸n de la funci贸n y se vuelve o retorna al punto donde fue llamada. Es por ello por lo que el c贸digo que va despu茅s del return no es ejecutado en el siguiente ejemplo.

def mi_funcion():
    print("Entra en mi_funcion")
    return
    print("No llega")
mi_funcion() # Entra en mi_funcion

Por ello, s贸lo llamamos a return una vez hemos acabado de hacer lo que ten铆amos que hacer en la funci贸n.

Por otro lado, se pueden devolver par谩metros. Normalmente las funciones son llamadas para realizar unos c谩lculos en base a una entrada, por lo que es interesante poder devolver ese resultado a quien llam贸 a la funci贸n.

def di_hola():
    return "Hola"
di_hola()
# 'Hola'

Tambi茅n es posible devolver mas de una variable, separadas por ,. En el siguiente ejemplo tenemos una funci贸n que calcula la suma y media de tres n煤meros, y devuelve su resultado.

def suma_y_media(a, b, c):
    suma = a+b+c
    media = suma/3
    return suma, media
suma, media = suma_y_media(9, 6, 3)
print(suma)  # 18
print(media) # 6.0

Documentaci贸n

Ahora que ya tenemos nuestras propias funciones creadas, tal vez alguien se interese en ellas y podamos compart铆rselas. Las funciones pueden ser muy complejas, y leer c贸digo ajeno no es tarea f谩cil. Es por ello por lo que es importante documentar las funciones. Es decir, a帽adir comentarios para indicar como deben ser usadas.

def mi_funcion_suma(a, b):
    """
    Descripci贸n de la funci贸n. Como debe ser usada,
    que par谩metros acepta y que devuelve
    """
    return a+b

Para ello debemos usar la triple comilla """ al principio de la funci贸n. Se trata de una especie de comentario que podemos usar para indicar como la funci贸n debe ser usada. No se trata de c贸digo, es un simple comentario un tanto especial, conocido como docstring.

Ahora cualquier persona que tenga nuestra funci贸n, podr谩 llamar a la funci贸n help() y obtener la ayuda de como debe ser usada.

help(mi_funcion_suma)

Otra forma de acceder a la documentaci贸n es la siguiente.

print(mi_funcion_suma.__doc__)

Para saber m谩s: Las descripciones de las funciones suelen ser un poco mas detalladas de lo que hemos mostrado. En la PEP257 se define en detalle como deber铆a ser.

Anotaciones en funciones

Existe una funcionalidad relativamente reciente en Python llamada function annotation o anotaciones en funciones. Dicha funcionalidad nos permite a帽adir metadatos a las funciones, indicando los tipos esperados tanto de entrada como de salida.

def multiplica_por_3(numero: int) -> int:
    return numero*3

multiplica_por_3(6) # 18

Las anotaciones son muy 煤tiles de cara a la documentaci贸n del c贸digo, pero no imponen ninguna norma sobre los tipos. Esto significa que se puede llamar a la funci贸n con un par谩metro que no sea int, y no obtendremos ning煤n error.

multiplica_por_3("Cadena")
# 'CadenaCadenaCadena'