Argumentos de función variádica en Python

PythonPythonBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

Esta sección aborda los argumentos de funciones variádicas, a veces descritos como *args y **kwargs.

Argumentos variables posicionales (*args)

Una función que acepta cualquier número de argumentos se dice que utiliza argumentos variables. Por ejemplo:

def f(x, *args):
  ...

Llamada a la función.

f(1,2,3,4,5)

Los argumentos adicionales se pasan como una tupla.

def f(x, *args):
    ## x -> 1
    ## args -> (2,3,4,5)

Argumentos variables de palabras clave (**kwargs)

Una función también puede aceptar cualquier número de argumentos de palabras clave. Por ejemplo:

def f(x, y, **kwargs):
 ...

Llamada a la función.

f(2, 3, flag=True, mode='fast', header='debug')

Las palabras clave adicionales se pasan en un diccionario.

def f(x, y, **kwargs):
    ## x -> 2
    ## y -> 3
    ## kwargs -> { 'flag': True,'mode': 'fast', 'header': 'debug' }

Combinando ambos

Una función también puede aceptar cualquier número de argumentos variables de palabras clave y no de palabras clave.

def f(*args, **kwargs):
...

Llamada a la función.

f(2, 3, flag=True, mode='fast', header='debug')

Los argumentos se separan en componentes posicionales y de palabras clave

def f(*args, **kwargs):
    ## args = (2, 3)
    ## kwargs -> { 'flag': True,'mode': 'fast', 'header': 'debug' }
  ...

Esta función acepta cualquier combinación de argumentos posicionales o de palabras clave. A veces se utiliza cuando se escriben envoltorios o cuando se desea pasar argumentos a otra función.

Pasando Tuplas y Diccionarios

Las tuplas se pueden expandir en argumentos variables.

numbers = (2,3,4)
f(1, *numbers)      ## Lo mismo que f(1,2,3,4)

Los diccionarios también se pueden expandir en argumentos de palabras clave.

options = {
    'color' : 'rojo',
    'delimitador' : ',',
    'ancho' : 400
}
f(data, **options)
## Lo mismo que f(data, color='rojo', delimitador=',', ancho=400)

Ejercicio 7.1: Un ejemplo simple de argumentos variables

Intenta definir la siguiente función:

>>> def avg(x,*more):
        return float(x+sum(more))/(1+len(more))

>>> avg(10,11)
10.5
>>> avg(3,4,5)
4.0
>>> avg(1,2,3,4,5,6)
3.5
>>>

Observa cómo el parámetro *more recopila todos los argumentos adicionales.

Ejercicio 7.2: Pasar tuplas y diccionarios como argumentos

Supongamos que lees algunos datos de un archivo y obtienes una tupla como esta:

>>> data = ('GOOG', 100, 490.1)
>>>

Ahora, supongamos que quieres crear un objeto Stock a partir de estos datos. Si intentas pasar data directamente, no funciona:

>>> from stock import Stock
>>> s = Stock(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Stock.__init__() missing 2 required positional arguments:'shares' and 'price'
>>>

Esto se soluciona fácilmente usando *data en su lugar. Prueba esto:

>>> s = Stock(*data)
>>> s
Stock('GOOG', 100, 490.1)
>>>

Si tienes un diccionario, puedes usar ** en su lugar. Por ejemplo:

>>> data = { 'name': 'GOOG','shares': 100, 'price': 490.1 }
>>> s = Stock(**data)
Stock('GOOG', 100, 490.1)
>>>

Ejercicio 7.3: Crear una lista de instancias

En tu programa report.py, creaste una lista de instancias usando código como este:

def read_portfolio(filename):
    '''
    Lee un archivo de cartera de acciones en una lista de diccionarios con claves
    name, shares y price.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                               select=['name','shares','price'],
                               types=[str,int,float])

    portfolio = [ Stock(d['name'], d['shares'], d['price'])
                  for d in portdicts ]
    return Portfolio(portfolio)

Puedes simplificar ese código usando Stock(**d) en su lugar. Haz ese cambio.

✨ Revisar Solución y Practicar

Ejercicio 7.4: Pasar argumentos sin modificar

La función fileparse.parse_csv() tiene algunas opciones para cambiar el delimitador del archivo y para el informe de errores. Tal vez desees exponer esas opciones a la función read_portfolio() anterior. Haz este cambio:

def read_portfolio(filename, **opts):
    '''
    Lee un archivo de cartera de acciones en una lista de diccionarios con claves
    name, shares y price.
    '''
    with open(filename) as lines:
        portdicts = fileparse.parse_csv(lines,
                                        select=['name','shares','price'],
                                        types=[str,int,float],
                                        **opts)

    portfolio = [ Stock(**d) for d in portdicts ]
    return Portfolio(portfolio)

Una vez que hayas hecho el cambio, intenta leer un archivo con algunos errores:

>>> import report
>>> port = report.read_portfolio('missing.csv')
Row 4: Couldn't convert ['MSFT', '', '51.23']
Row 4: Reason invalid literal for int() with base 10: ''
Row 7: Couldn't convert ['IBM', '', '70.44']
Row 7: Reason invalid literal for int() with base 10: ''
>>>

Ahora, intenta silenciar los errores:

>>> import report
>>> port = report.read_portfolio('missing.csv', silence_errors=True)
>>>
✨ Revisar Solución y Practicar

Resumen

¡Felicitaciones! Has completado el laboratorio de Argumentos Variables. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.