La función zip() en Python
En Python y todos los lenguajes de programación, podemos usar bucles for
y while
para iterar sobre matrices. Iterar sobre una sola matriz es muy simple. Sin embargo, cuando se trata de iterar varias matrices juntas, las cosas comienzan a volverse complejas. Si el tamaño de todas las matrices es el mismo, entonces es un trabajo sencillo. Pero si los tamaños de los arreglos son diferentes, debemos asegurarnos de que solo consideramos la longitud del arreglo más pequeño para evitar errores y excepciones.
Python hace que esta tarea sea mucho más fácil. En lugar de escribir manualmente la lógica para iterar matrices de diferentes tamaños, podemos usar una utilidad integrada, más precisamente una función, proporcionada por Python. Esta función es la función zip()
.
Este artículo presentará la función zip()
y cómo usarla.
La función zip()
en Python
La función zip()
acepta objetos iterables como listas, cadenas y tuplas como argumentos y devuelve un solo iterable.
El objeto iterable devuelto tiene la longitud de los iterables más pequeños. Por ejemplo, si se proporcionan dos listas de tamaño 5
y 10
a la función zip()
, el objeto iterable devuelto tendrá una longitud de 5
. Esto significa que solo los primeros 5
elementos de la segunda lista serán parte del objeto iterable. Si a esta función se le asigna un objeto iterable vacío o no iterable, también devuelve un objeto iterable vacío.
Ahora que hemos terminado con la teoría, veamos cómo usar esta función. Consulte los siguientes ejemplos para comprender su uso.
Ningún objeto iterable
En el siguiente código de Python, no se pasará ningún objeto iterable a la función zip()
.
result = zip()
for x in result:
print(x)
No se imprimirá nada en la consola cuando ejecutemos el código anterior. La razón detrás de lo mismo es simple; si no se proporcionara ningún objeto iterable, no tendríamos nada sobre lo que iterar. Por lo tanto, se devuelve un objeto iterable vacío.
Objetos iterables de la misma longitud
En el siguiente código de Python, se pasará a la función zip()
una tupla de enteros, una lista de valores flotantes, una lista de objetos de clase y una cadena de longitudes iguales.
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
for x in result:
print(x)
Producción :
(11, 1.1, Number(1), 'H')
(22, 2.2, Number(23), 'e')
(33, 3.3, Number(44.44), 'l')
(44, 4.4, Number(0), 'l')
(55, 5.5, Number(-9), 'o')
Como podemos ver, la función zip()
almacena valores en todos los objetos iterables juntos en tuplas. El orden de los valores dentro de las tuplas es el mismo que el orden en que se proporcionaron sus objetos iterables a la función zip()
.
Podemos desestructurar o desempaquetar estos valores dentro del bucle for
para facilitar el acceso. Consulte el siguiente código para lo mismo.
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
for p, q, r, s in result:
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
Producción :
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
A: 44
B: 4.4
C: Number(0)
D: l
A: 55
B: 5.5
C: Number(-9)
D: o
En lugar de usar bucles for
, también podemos iterar sobre un objeto iterable usando un bucle while
. Con los bucles while
, necesitaríamos dos cosas adicionales, la función next()
y un bloque try-except
. La función next()
se utilizará para obtener valores del objeto iterable devuelto por la función zip()
, y el bloque try...except
se utilizará para detener la iteración. Consulte el siguiente código de Python para lo mismo.
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33, 44, 55)
b = [1.1, 2.2, 3.3, 4.4, 5.5]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "Hello"
result = zip(a, b, c, d)
while True:
try:
p, q, r, s = next(result)
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
except StopIteration:
break
Producción :
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
A: 44
B: 4.4
C: Number(0)
D: l
A: 55
B: 5.5
C: Number(-9)
D: o
Cuando no hay valores disponibles dentro de un iterador, genera una excepción StopIteration
. Usando un bloque try-except
, capturamos esta excepción y salimos del bucle infinito while
.
Objetos iterables de diferentes longitudes
En el siguiente código de Python, se pasará a la función zip()
una tupla de enteros, una lista de valores flotantes, una lista de objetos de clase y una cadena de diferentes longitudes.
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33)
b = [1.1, 2.2, 3.3, 4.4]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "HelloWorld"
result = zip(a, b, c, d)
for p, q, r, s in result:
print("A:", p)
print("B:", q)
print("C:", r)
print("D:", s)
Producción :
A: 11
B: 1.1
C: Number(1)
D: H
A: 22
B: 2.2
C: Number(23)
D: e
A: 33
B: 3.3
C: Number(44.44)
D: l
Todos los objetos iterables tienen diferentes longitudes. El primer objeto iterable o la tupla de enteros tiene la menor longitud, 3
. Por lo tanto, la salida solo imprime los primeros 3
valores de todos los objetos iterables.
Creación de un diccionario
Podemos crear un diccionario de pares clave-valor con la ayuda de la función zip()
. La idea es crear un iterador de dos arreglos de la misma longitud, que contengan claves y sus respectivos valores, y mapearlos entre sí dentro de un diccionario mientras se itera sobre el objeto iterable devuelto. Consulte el siguiente código para lo mismo.
import json
a = ["W", "O", "R", "L", "D"]
b = [1.1, True, "Hello", None, 5]
result = zip(a, b)
mapping = {x: y for x, y in result}
print(json.dumps(mapping, indent=4))
Producción :
{
"W": 1.1,
"O": true,
"R": "Hello",
"L": null,
"D": 5
}
El código anterior solo usa el módulo json
para embellecer la salida del diccionario. Tenga en cuenta que su uso es completamente opcional.
Uso de la función zip()
junto con la función enumerate()
La función enumerate()
se usa para obtener el índice y el valor al mismo tiempo mientras se itera sobre un objeto iterable. Dado que la función zip()
devuelve un iterador, podemos juntar las dos funciones y tener acceso a los índices y los valores. Consulte el siguiente código de Python para lo mismo.
class Number:
def __init__(self, number):
self.number = number
def square(self):
return number ** 2
def __repr__(self):
return f"Number({self.number})"
a = (11, 22, 33)
b = [1.1, 2.2, 3.3, 4.4]
c = [Number(1), Number(23), Number(44.44), Number(0), Number(-9)]
d = "HelloWorld"
result = zip(a, b, c, d)
for i, (p, q, r, s) in enumerate(result):
print(f"A{i + 1}:", p)
print(f"B{i + 1}:", q)
print(f"C{i + 1}:", r)
print(f"D{i + 1}:", s)
Producción :
A1: 11
B1: 1.1
C1: Number(1)
D1: H
A2: 22
B2: 2.2
C2: Number(23)
D2: e
A3: 33
B3: 3.3
C3: Number(44.44)
D3: l
En el código de Python anterior, dentro del bucle for
, i, (p, q, r, s)
desempaqueta los valores devueltos por la función enumerate()
, y (p, q, r, s)
descomprima los valores devueltos por la función zip()
.
Los valores devueltos por la función enumerate()
están en el siguiente formato.
(0, (11, 1.1, Number(1), "H"))
(1, (22, 2.2, Number(23), "e"))
(2, (33, 3.3, Number(44.44), "l"))
Aclara por qué se usó i, (p, q, r, s)
para desempaquetar todos los valores.