Python es el lenguaje de programación más utilizado. Hoy aprenderá a usar una de sus funciones principales, pero a menudo ignorada, descomprimiéndola en Python.
Probablemente hayas visto * y ** en el código de otros o incluso los hayas usado sin saber realmente cuál es su propósito. Analizaremos el concepto de desempaquetado y cómo usarlo para escribir más código Pythonic.
Aquí hay una lista de conceptos que le resultarán útiles al leer este tutorial:
- Iterable: Cualquier secuencia que pueda ser iterada por un en bucle, como conjuntos, liza, tuplas y diccionarios
- Invocable: Un objeto de Python que se puede llamar usando doble paréntesis (), por ejemplo, myfunction ()
- Cáscara: Entorno de ejecución interactivo que nos permite ejecutar código Python. Podemos llamarlo ejecutando "python" en una terminal
- Variable: Nombre simbólico que almacena un objeto y tiene una ubicación de memoria reservada.
Comencemos con la confusión más frecuente: las asterísticas en Python también son operadores aritméticos. Un asterisco (*) se usa para la multiplicación, mientras que dos de ellos (**) se refieren a exponenciación.
Podemos demostrarlo abriendo un shell de Python y escribiendo:
>>> 3*3
9
>>> 3**3
27
Nota: Debe tener Python 3 instalado para seguir este tutorial. Si no lo tiene instalado, consulte nuestro Guía de instalación de Python.
Como puede ver, usamos el asterisco después del primer número y antes del segundo. Cuando ve esto, significa que estamos usando los operadores aritméticos.
Por otro lado, usamos los asteriscos (*, **) antes de un iterable para descomprimirlo, por ejemplo:
>>> *range(1, 6),
(1, 2, 3, 4, 5)
>>> {**{'vanilla':3, 'chocolate':2}, 'strawberry':2}
{'vanilla': 3, 'chocolate': 2, 'strawberry': 2}
No se preocupe si no lo obtiene, esto es solo un preámbulo para desempaquetar en Python. ¡Así que sigue adelante y lee el tutorial completo!
What’s unpacking?
Desembalar es el proceso de sacar cosas: iterables como listas, tuplas y diccionarios. Piense en ello como abrir una caja y sacar diferentes elementos como cables, auriculareso un USB.

Traduzcamos este mismo ejemplo en código para una mejor comprensión:
>>> mybox = ['cables', 'headphones', 'USB']
>>> item1, item2, item3 = mybox
Como puede ver, estamos asignando los tres elementos dentro del mybox lista de tres variables artículo1, artículo2, artículo2. Este tipo de asignación de variables es el concepto fundamental de descomprimir en Python.
Si intenta obtener el valor de cada artículo, notará que item1, se refiere a "cables", item2, se refiere a "auriculares" y así sucesivamente.
>>> item1
'cables'
>>> item2
'headphones'
>>> item3
'USB'
Hasta aquí, todo parece ir bien con este código, pero ¿y si quisiéramos descomprimir una lista con más elementos, manteniendo la misma cantidad de variables asignadas?
>>> newbox = ['cables', 'headphones', 'USB', 'mouse']
>>> item1, item2, item3 = newbox
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)
Probablemente esperabas este tipo de error. Básicamente, estamos asignando 4 elementos de lista a tres variables, ¿cómo se las arregla Python para asignar los valores correctos?
No es así, eso es porque obtenemos un ValorError con el mensaje "demasiados valores para descomprimir". Esto está sucediendo porque estamos estableciendo Tres variables a la izquierda, y Digital XNUMXk valores (correspondientes a la lista newbox) a la derecha.
Si intenta hacer un proceso similar, pero con más variables que valores para descomprimir, obtendrá otro ValorError excepto que con un mensaje ligeramente diferente:
>>> lastbox = ['cables', 'headphones']
>>> item1, item2, item3 = lastbox
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
Nota: hemos estado trabajando con listas, pero puede utilizar esta forma de descomprimir con cualquier iterable (listas, conjuntos, tuplas, diccionarios).
Entonces, ¿cómo superamos esta situación? ¿Hay alguna forma de descomprimir todos los elementos de un iterable en un par de variables sin obtener ningún error?
Seguro que lo hay, y se llama operador de desembalaje u operador de asterisco (*, **). Veamos cómo usarlo en Python.
How to Unpack Lists With the * operator
El operador de asterisco (*) se utiliza para descomprimir todos los valores de un iterable que aún no se han asignado.
Supongamos que desea obtener el primer y último elemento de una lista sin usar índices, podríamos hacerlo con el operador asterisco:
>>> first, *unused, last = [1, 2, 3, 5, 7]
>>> first
1
>>> last
7
>>> unused
[2, 3, 5]
Como puede apreciar, obtenemos todos los valores no utilizados con el operador asterisco. La forma preferida de descartar valores es usar una variable de subrayado (_), que a veces se usa como una "variable ficticia".
>>> first, *_, last = [1, 2, 3, 5, 7]
>>> _
[2, 3, 5]
Todavía podemos usar este truco incluso si la lista solo tiene dos elementos:
>>> first, *_, last = [1, 2]
>>> first
1
>>> last
2
>>> _
[]
En este caso, la variable de subrayado (variable ficticia) almacena una lista vacía para que las otras dos variables a su alrededor puedan acceder a los valores disponibles de la lista.
Solución de problemas comunes
Podemos descomprimir un elemento único de un iterable. Por ejemplo, se te ocurriría algo como esto:
>>> *string = 'PythonIsTheBest'
Sin embargo, el código anterior devolverá un Error de sintaxis:
>>> *string = 'PythonIsTheBest'
File "<stdin>", line 1
SyntaxError: starred assignment target must be in a list or tuple
Esto porque de acuerdo con el Especificación PEP:
Una tupla (o lista) en el lado izquierdo de una tarea simple
Si queremos descomprimir todos los valores de un iterable en una sola variable, debemos configurar una tupla, por lo que agregar una simple coma será suficiente:
>>> *string, = 'PythonIsTheBest'
>>> string
['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']
Otro ejemplo sería el uso de distancia función, que devuelve una secuencia de números.
>>> *numbers, = range(5)
>>> numbers
[0, 1, 2, 3, 4]
Ahora que sabe cómo descomprimir listas y tuplas con un asterisco, es hora de comenzar a descomprimir diccionarios.
How to Unpack Dictionaries With ** operator
Mientras que un solo asterisco se usa para descomprimir listas y tuplas, el doble asterisco (**) se usa para descomprimir diccionarios.
Desafortunadamente, no podemos descomprimir un diccionario en una sola variable como lo hemos estado haciendo con tuplas y listas. Eso significa que lo siguiente arrojará un error:
>>> **greetings, = {'hello': 'HELLO', 'bye':'BYE'}
...
SyntaxError: invalid syntax
Sin embargo, podemos usar el operador ** dentro de los callables y otros diccionarios. Por ejemplo, si queremos crear un diccionario combinado, hecho a partir de otros diccionarios, podríamos usar el siguiente código:
>>> food = {'fish':3, 'meat':5, 'pasta':9}
>>> colors = {'red': 'intensity', 'yellow':'happiness'}
>>> merged_dict = {**food, **colors}
>>> merged_dict
{'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}
Esta es una forma bastante corta de crear diccionarios compuestos, sin embargo, este no es el enfoque principal para desempaquetar en Python.
Veamos cómo podemos usar el desempaquetado con llamadas
Packing in Functions: args and kwargs
Probablemente haya visto args y kwargs antes implementados en clases o funciones. Veamos por qué necesitamos usarlos junto con las llamadas.
Empaquetado con el operador * (args)
Supongamos que tenemos una función que calcula el producto de dos números.
>>> def product(n1, n2):
... return n1 * n2
...
>>> numbers = [12, 1]
>>> product(*numbers)
12
Como puede ver, estamos desempaquetando la lista. números a la función, por lo que en realidad estamos ejecutando lo siguiente:
>>> product(12, 1)
12
Hasta aquí, todo funciona bien, pero ¿y si quisiéramos pasar una lista más larga? Ciertamente generará un error porque la función está recibiendo más argumentos de los que es capaz de administrar.
>>> numbers = [12, 1, 3, 4]
>>> product(*numbers)
...
TypeError: product() takes 2 positional arguments but 4 were given
Podemos resolver todo esto con solo embalaje la lista directamente en la función, lo que crea un iterable dentro de ella y nos permite pasar cualquier número de argumentos a la función.
>>> def product(*args):
... result = 1
... for i in args:
... result *= i
... return result
...
>>> product(*numbers)
144
Aquí estamos tratando el args parámetro como iterable, recorriendo sus elementos y devolviendo el producto de todos los números. Tenga en cuenta que el número inicial del resultado debe ser uno porque si comenzamos con cero, la función siempre devolverá cero.
Nota: args es solo una convención, puede usar cualquier otro nombre de parámetro
También podríamos pasar números arbitrarios a la función sin usar una lista, al igual que con la función incorporada función de impresión.
>>> product(5, 5, 5)
125
>>> print(5, 5, 5)
5 5 5
Finalmente, obtengamos el tipo de objeto del args de una función.
>>> def test_type(*args):
... print(type(args))
... print(args)
...
>>> test_type(1, 2, 4, 'a string')
<class 'tuple'>
(1, 2, 4, 'a string')
Como se indica en el código anterior, el tipo de args será siempre tupla, y su contenido serán todos los argumentos sin palabras clave que se pasen a la función.
Embalaje con el operador ** (kwargs)
Como vimos anteriormente, el operador ** se usa exclusivamente para diccionarios. Esto significa que con este operador podemos pasar pares clave-valor a la función como parámetro.
Creemos una función hacer_persona, que recibe un "nombre" de argumento posicional y una cantidad indefinida de argumentos con palabras clave.
>>> def make_person(name, **kwargs):
... result = name + ': '
... for key, value in kwargs.items():
... result += f'{key} = {value}, '
... return result
...
>>> make_person('Melissa', id=12112, location='london', net_worth=12000)
'Melissa: id = 12112, location = london, net_worth = 12000, '
Como se puede ver, el ** kwargs declaración convierte todos los argumentos con palabras clave en un diccionario, que podemos iterar dentro de la función.
Nota: kwargs es solo una convención, puedes nombrar este parámetro con lo que quieras
Podemos comprobar el tipo de kwargs de la misma manera que lo hicimos con args:
>>> def test_kwargs(**kwargs):
... print(type(kwargs))
... print(kwargs)
...
>>> test_kwargs(random=12, parameters=21)
<class 'dict'>
{'random': 12, 'parameters': 21}
EL kwargs La variable interna siempre se convierte en un diccionario, que almacena los pares clave-valor pasados a la función.
Finalmente, hagamos uso de args y kwargs en la misma función:
>>> def my_final_function(*args, **kwargs):
... print('Type args: ', type(args))
... print('args: ', args)
... print('Type kwargs: ', type(kwargs))
... print('kwargs: ', kwargs)
...
>>> my_final_function('Python', 'The', 'Best', language='Python', users='A lot')
Type args: <class 'tuple'>
args: ('Python', 'The', 'Best')
Type kwargs: <class 'dict'>
kwargs: {'language': 'Python', 'users': 'A lot'}
Conclusión
Los operadores de descompresión son realmente útiles en las tareas del día a día, ahora sabe cómo usarlos tanto en declaraciones individuales como en parámetros de funciones.
En este tutorial aprendiste:
- Usas * para tuplas y listas y ** para diccionarios
- Puede utilizar operadores de desempaquetado en constructores de funciones y clases
- args se utilizan para pasar parámetros sin palabras clave a funciones
- kwargs se utilizan para pasar parámetros con palabras clave a funciones.