Diferencias entre lista-tupla-conjunto-diccionario, resumiendo cuándo usarlas
Python tiene cuatro tipos de contenedores incorporados: List, Tuple, Dictionary, Set.
En este artículo, compararemos las propiedades de cada tipo y resumiremos cuándo usarlos.
1. Listas vs. Tuplas
Las listas y las tuplas son los tipos más similares. Para empezar, ambos tipos tienen un orden, y puedes usar un índice para obtener sus elementos. Además, puedes tener múltiples tipos de elementos en una sola lista o tupla. Por ello, puedes utilizar ambos tipos en muchos casos.
Para aclarar los usos de ambos tipos, es importante tener en cuenta las diferencias. En esta sección, discutiremos las diferencias entre los dos tipos para orientarte sobre cuándo usarlos.
1.1. Inmutabilidad
La diferencia más importante entre listas y tuplas es la inmutabilidad. Las listas pueden añadirse y eliminarse libremente, y los elementos de una lista pueden modificarse con facilidad. Las tuplas, en cambio, no pueden añadirse, borrarse o modificarse una vez declaradas.
Pensemos cuándo necesitamos la inmutabilidad en una aplicación real y cuándo no.
Se nos ha encomendado la tarea de implementar varias características de un carrito de la compra utilizando los tipos contenedores de Python. Las características básicas de un carrito de la compra que necesitan ser agregables y removibles son la lista de productos, el carrito de la compra y la lista de usuarios. Estas características deben utilizar listas.
Por el contrario, ¿qué características necesitan ser inmutables? Se podría pensar en metadatos que no cambian, como el nombre de usuario de un usuario, la fecha de inicio de sesión o el número de licencia comercial de un comerciante. Esta información se almacena mejor en tuplas para que los datos no puedan cambiarse inadvertidamente.
Pensar en la inmutabilidad en el diseño de tu aplicación también te ayudará a comunicarte con otros desarrolladores. Esto se debe a que puedes expresar en el propio código que una característica implementada como una lista es inmutable, mientras que una característica implementada como una tupla no debe ser modificada.
1.2. Diversidad de tipos
Como se mencionó anteriormente, tanto las listas como las tuplas pueden contener elementos de múltiples tipos juntos. Sin embargo, si pensamos en ellas como una extensión de la sección anterior, la historia puede ser diferente.
Hemos mencionado que las listas se utilizan para cosas como listas de formularios, listas de carritos de la compra, listas de usuarios, etcétera. Estas listas escogen los mismos tipos de elementos. Una lista de carro de la compra contendría sólo productos, una lista de usuarios contendría sólo usuarios, y así sucesivamente.
usuarios = [usuario1, usuario2, usuario3].
Por otro lado, si pensamos en los metadatos de un usuario como una tupla, los elementos de la tupla serían de distintos tipos.
Usuario1 = ('ID', 'Creado en', 'Número de registro de empresa', ... )
Y estas tuplas de datos se pueden ensamblar en una lista.
Usuarios = [
('Usuario1', 'ID', 'Creado en', 'Número de Registro', ... )
('Usuario2', 'ID', 'Creado el', 'Número de Registro de Empresa', ... )
('Usuario3', 'ID', 'Creado en', 'Número de registro de la empresa', ... )
]
1.3. Resumen
En resumen, las tuplas se pueden utilizar para mantener varias piezas de información sobre un único objeto, actuando como una clase simple. Las listas se pueden utilizar para gestionar múltiples objetos formados por tuplas como una lista. Estos son los usos más comunes de las listas y las tuplas.
Aquí mencionaremos uno más. La lista de productos de un carrito de la compra sólo debe ser accesible para los usuarios del carrito, y la lista de usuarios sólo debe ser accesible para los administradores del servicio. Esa es una regla que no va a cambiar. Así que ¿por qué no gestionar las listas que son accesibles a los diferentes usuarios como tuplas como esta?
admin_lists = ([Usuario1, Usuario2, ... ], ... )
listas_clientes = ([articulo1, articulo2, ... ], ... )
Como puedes ver, cuando incluyes una lista en una tupla, los elementos de esa lista son modificables. Esto se debe a que la inmutabilidad de la tupla se aplica a la referencia a la lista en sí, no a los elementos que contiene.
2. Diccionarios
La principal característica que distingue a los diccionarios de los otros tres tipos son los pares clave-valor que componen un diccionario.
Las claves de un diccionario actúan como los índices de una lista o tupla. Mientras que una lista o tupla utilizaría un índice numérico para recuperar un elemento concreto, un diccionario puede utilizar cualquier tipo con inmutabilidad garantizada como clave para recuperar un valor.
Estas claves inmutables pueden utilizarse como objetivos de la tabla hash en la que se basa el diccionario.
Esto tiene la ventaja de que comprobar si una clave está contenida en un diccionario, o recuperar un valor mediante una clave, puede hacerse con una complejidad de tiempo O(1)
de media.
Esto es económico comparado con recorrer listas y tuplas hasta O(n)
para determinar si un elemento está incluido o no.
Como son diccionarios que pueden utilizar valores clave, son más fáciles de modelar que las tuplas. Puedes organizar la información de un producto o de un usuario como se muestra a continuación. Especialmente para la información que necesita ser libremente modificable.
Cubriré esto en un post aparte, pero la información de atributos inmutables se gestiona fácilmente con el tipo NamedTuple.
Item1 = {
"nombre": "Producto A",
"precio": 50.00,
"descripción": "Descripción A",
"stock": 10,
}
Usuario1 = {
"nombre": "Juan Pérez",
"email": "john@example.com",
"dirección": "Calle 123"
}
Como puedes ver, los diccionarios de Python son una forma práctica de implementar cualquier objeto que necesite propiedades y valores de propiedades.
3. Conjuntos
Hay dos características principales que distinguen el tipo conjunto de los otros tres tipos.
Una es que no permite duplicados.
Los conjuntos se deduplican a sí mismos cuando añades un nuevo valor con el método set.add()
, o cuando conviertes otro tipo contenedor con el constructor set()
.
Esto hace que la deduplicación sea más fácil que en otros lenguajes.
Un patrón popular de deduplicación es convertir un tipo en un conjunto y viceversa, como se muestra a continuación.
números = [1, 2, 2, 3, 3, 3, 4, 5].
números_únicos = list(conjunto(números))
print(números_únicos)
# Salida: [1, 2, 3, 4, 5]
La segunda propiedad de los conjuntos es que son eficaces para determinar la inclusión. En 2.Diccionarios, vimos que se puede utilizar una tabla hash para determinar eficientemente si una clave está incluida o no. Los valores de un conjunto también se organizan en una tabla hash. Esto nos permite determinar rápidamente si un elemento está incluido o no.
Además, el tipo conjunto tiene métodos incorporados para informarle sobre las relaciones de intersección, unión, diferencia y agregación. Esto también significa que no tienes que escribir código para estas funciones.
Por ejemplo, si quisieras comparar las relaciones de contención de dos listas, podrías hacer algo como esto
frutas_en_mercado = ['manzana', 'plátano', 'naranja', 'piña'].
carrito = ['plátano', 'naranja'].
set_frutas_en_mercado = set(frutas_en_mercado)
is_superset = set_frutas_en_mercado.issuperset(carrito)
print(es_superconjunto)
# Salida: True
Convirtiendo sólo una de nuestras listas en un conjunto, podemos hacer cosas muy potentes con un código tan sencillo como el anterior.
Consideremos ahora la funcionalidad de un carrito de la compra, que aprovecha dos grandes características de los conjuntos.
En primer lugar, podemos construir una lista de categorías de las que necesitamos eliminar duplicados, como se muestra a continuación, o podemos utilizar
product_categories = {"Electrónica", "Libros", "Ropa", "Decoración", "Comida"}
Comparando la lista de deseos con el conjunto de la cesta de la compra, también podemos utilizar la lista de deseos para marcar los artículos de la cesta de la compra con un corazón.
lista_deseos = ['iPhone 14 pro', 'PlayStaion 5', 'Bose QC 45'].
carrito = ['PlayStaion 5', 'Nintendo Switch'].
lista_corazones = set(lista_deseos).intersection(carrito)
print(lista_corazones)
# Salida: {'PlayStaion 5'}
4. Conclusión
En esta sección, hemos visto las características y usos de los tipos contenedores incorporados en Python. Los he resumido para ayudarte a tener una idea general de los cuatro tipos, pero mantén siempre la mente abierta y piensa creativamente en cómo usarlos.
Para más información sobre cada tipo, consulta el sub-post correspondiente.