Funciones: Argumentos#

Important

¿Qué sabemos de las funciones?

En el cuaderno anterior, aprendimos a definir y a invocar funciones. Ahora aprenderemos la manera de manipular los argumentos de las funciones que creemos.

Argumentos por defecto:#

En la función que calculaba el valor, con y sin impuestos, de una cuenta en un cierto restaurante nos hizo falta incluir el valor de la propina, ajuste que realizaremos en este momento:

def costos(comensales,propina=10):
    Cuenta = round(comensales*50000,2)
    CuentaSinImp = round(Cuenta*100/108,2)
    CuentaConProp = round(Cuenta*(1+propina/100),2)
    x = '''    Valor Neto: '''+str(CuentaSinImp)+'''
    Total sin propina: '''+ str(Cuenta)+ '''
    Total con propina: '''+ str(CuentaConProp)
    print(x)
costos(1)
    Valor Neto: 46296.3
    Total sin propina: 50000
    Total con propina: 55000.0

Nota que en la función anterior el segundo argumento tiene un valor predeterminado propina=10, esto quiere decir que, si no modificamos su valor, la función asumirá este como el valor predeterminado, es decir, las propinas serán del \(10\%\) salvo que se indique algún otro valor. Por ejemplo si deseamos calcular el total de la cuenta con una propina del \(7\%\), ejecutamos las siguientes líneas de código:

costos(1,7)
#Estamos considerando los argumentos posicionalmente
    Valor Neto: 46296.3
    Total sin propina: 50000
    Total con propina: 53500.0
costos(propina=7,comensales=1)
#Estamos haciendo referencia directa al valor de los argumentos
    Valor Neto: 46296.3
    Total sin propina: 50000
    Total con propina: 53500.0

Lo presentado en la línea anterior suele emplearse únicamente cuando se tienen diferentes variables predeterminadas y no con las variables obligatorias, esto con el fin de evitar malas interpretaciones de las entradas.

Argumentos opcionales:#

En diversos lenguajes de programación existe dos tipos de argumentos ampliamente utilizados args (arguments: argumentos opcionales no nombrados) y kwargs (keywordarguments: argumentos opcionales nombrados), en Python los args son tuplas y los kwargs son diccionarios (estructuras que estudiaremos en profundidad más adelante), estos argumentos permiten agregar cualquier cantidad de entradas a las funciones como podemos ver en las siguientes funciones:

def f1(*args):
    return sum(args)
f1(1,2,3,4,5)
15
f1(1,2.3)
3.3
#Note que si se introduce un argumento no numérico la función generará un error
f1('hola')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [8], in <cell line: 2>()
      1 #Note que si se introduce un argumento no numérico la función generará un error
----> 2 f1('hola')

Input In [5], in f1(*args)
      1 def f1(*args):
----> 2     return sum(args)

TypeError: unsupported operand type(s) for +: 'int' and 'str'

Este tipo de argumentos nos permite definir, entre muchas otras, una función que calcule el promedio de una lista de números dados

def promedio(*args):
    return sum(args)/len(args)
promedio(1,2,3,4,5.2,3.1,4)
3.185714285714286

Es importante que note que en la definición de la función, el argumento que será una tupla de tamaño indefinido lleva un * antes, esto es lo que le indica a Python el tipo de variable que es, y dentro de la función se utiliza la variable sin el *. El nombre puede ser cualquiera pero por convención suele emplearse args.

Los tipos de entrada de estas variables pueden ser diversos, por ejemplo:

def imprime(*args):
    if len(args)==0:
        print('No hubo argumentos de entrada.')
    else:
        for i in range(len(args)):
            print('En la entrada {0} se almacenó: {1} y es del tipo {2}'.format(i,args[i],type(args[i])))
imprime()
No hubo argumentos de entrada.
imprime('hola',1)
En la entrada 0 se almacenó: hola y es del tipo <class 'str'>
En la entrada 1 se almacenó: 1 y es del tipo <class 'int'>

También podemos combinar las variables bien sean obligatorias u opcionales con este tipo de argumentos, por ejemplo:

def f2(arg1, *argv):
    print ("Primer argumento :", arg1)
    for arg in argv:
        print("Siguiente argumento en la tupla *argv :", arg)
f2('Hola', 'bienvenido', 'a', 'la', 'Universidad','Externado','de', 'Colombia')
Primer argumento : Hola
Siguiente argumento en la tupla *argv : bienvenido
Siguiente argumento en la tupla *argv : a
Siguiente argumento en la tupla *argv : la
Siguiente argumento en la tupla *argv : Universidad
Siguiente argumento en la tupla *argv : Externado
Siguiente argumento en la tupla *argv : de
Siguiente argumento en la tupla *argv : Colombia

Si intentamos escribir primero las variables de tamaño indefinido y luego las que necesitamos realmente obtendremos un error, ya que Python no sabrá en qué momento debe parar de llenar la tupla y seguir con los argumentos fijos, salvo que se especifiquen sus valores como vimos anteriormente:

def f3(*argv,argn):
    print ("Último argumento :", argn)
    for arg in argv:
        print("Siguiente argumento en la tupla *argv :", arg)
f3('Hola', 'bienvenido', 'a', 'la', 'Universidad','Externado','de', 'Colombia')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-36a5f8de1e71> in <module>
----> 1 f3('Hola', 'bienvenido', 'a', 'la', 'Universidad','Externado','de', 'Colombia')

TypeError: f3() missing 1 required keyword-only argument: 'argn'
f3('Hola', 'bienvenido', 'a', 'la', 'Universidad','Externado','de', argn='Colombia')
Último argumento : Colombia
Siguiente argumento en la tupla *argv : Hola
Siguiente argumento en la tupla *argv : bienvenido
Siguiente argumento en la tupla *argv : a
Siguiente argumento en la tupla *argv : la
Siguiente argumento en la tupla *argv : Universidad
Siguiente argumento en la tupla *argv : Externado
Siguiente argumento en la tupla *argv : de

Ejercicios:#

  1. Crea una función que permita hallar la mediana en una lista de números ingresados en orden ascendente.

  2. Crea una función que calcule la varianza muestral de los valores ingresados.$\(\text{varianza} = \sigma^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar{x})^2,\)\( \)n=\text{tamaño de la muestra} \( \)\bar{x} = promedio\( \)x_i = i-\text{ésimo elemento de la muestra} $

  3. Cree una función que halle el mínimo de una lista de números dados.

  4. Cree una función que halle el máximo de una lista de números dados.

Para introducir los kwargs es necesario en el argumento de la función a dicha variable antecederla de **, por ejemplo:

def fkw1(**kwargs):
    for nombre, valor in kwargs.items():
        print("{0} = {1}".format(nombre, valor))
fkw1(nota1=1.0,nota2=3.5,nota3=5)
nota1 = 1.0
nota2 = 3.5
nota3 = 5

Ejercicio:#

  1. Modifica el código anterior para que el programa calcule el promedio de las notas ingresadas.

En una función de Python podemos tener variables de todo tipo involucradas, como por ejemplo:

def superfuncion(a,b=5,*args,**kwargs):
    print('El valor del único parámetro obligatorio es: ',a)
    print('El valor del único parámetro con valor predeterminado es: ',b)
    print('Los valores ingresados en la tupla args son: ',args)
    print('Los valores ingresados en el diccionario **kwargs son: ',kwargs)
superfuncion(1)
El valor del único parámetro obligatorio es:  1
El valor del único parámetro con valor predeterminado es:  5
Los valores ingresados en la tupla args son:  ()
Los valores ingresados en el diccionario **kwargs son:  {}
superfuncion(1,2)
El valor del único parámetro obligatorio es:  1
El valor del único parámetro con valor predeterminado es:  2
Los valores ingresados en la tupla args son:  ()
Los valores ingresados en el diccionario **kwargs son:  {}
superfuncion(1,2,0,1,2,3)
El valor del único parámetro obligatorio es:  1
El valor del único parámetro con valor predeterminado es:  2
Los valores ingresados en la tupla args son:  (0, 1, 2, 3)
Los valores ingresados en el diccionario **kwargs son:  {}
superfuncion(1,2,0,1,2,3,val0=0,val1=1,val2=2)
El valor del único parámetro obligatorio es:  1
El valor del único parámetro con valor predeterminado es:  2
Los valores ingresados en la tupla args son:  (0, 1, 2, 3)
Los valores ingresados en el diccionario **kwargs son:  {'val0': 0, 'val1': 1, 'val2': 2}

En este ejemplo podemos ver la clara diferencia entre la tupla almacenada en args y el diccionario almacenado en kwargs, su manipulación será objeto de cuadernos posteriores, pero es bueno que desde ya tengamos presente su existencia, ya que posteriormente nos serán de gran utilidad.

Ejercicio:#

  1. Cree una función que dado un monto y una lista de personas con sus correspondientes invitados, calcule cuánto debe pagar cada uno si la cuenta se divide en partes iguales.

  2. Haga un programa que le permita ingresar las notas obtenidas por un estudiante y los porcentajes asociados a ellas, si el porcentaje es del \(100\%\) debe arrojar la nota definitiva de la materia y si el porcentaje es inferior debe informarle el valor de la nota acumulada y cuánto debería sacar en el resto de la materia para aprobarla.

Comentarios finales:#

Recuerda que para evitar confusiones en la ejecución de la función los parámetros de esta deben ir así: variables, variables con asignaciones predeterminadas, args y kwargs

def nombre_de_la_función(v1,...,vn,vp1='algo',...,vpm='algo',*args,**kwargs):
    lista_de_instrucciones
    return resultado