En Python, una colección es un objeto que contiene un grupo de elementos y permite manipularlos como una unidad única.
Las colecciones generalmente admiten:
- iteración (
for elemento in coleccion) - verificación de pertenencia (
x in coleccion) - determinación de longitud (
len(coleccion)) - acceso por índice o clave (si está ordenada o es asociativa)
Python no tiene una «interfaz de colección» estricta, pero sigue protocolos informales. Si un objeto implementa
__iter__,__len__,__contains__, puede considerarse una colección.
- Lo que NO es una colección
- Colecciones integradas
- Colecciones extendidas de la biblioteca estándar
- Otros tipos similares a colecciones
- 1. Listas —
list - 2. Diccionarios —
dict - 3. Tuplas —
tuple - 4. SimpleNamespace
- 5. Conjuntos —
set - 6. Conjuntos inmutables —
frozenset - 7. namedtuple — tuplas con nombre
- 8. deque — cola de doble extremo
- 9. Counter — contador de elementos
- 10. defaultdict — diccionario con valores por defecto
- 11. dataclass — clases de datos
- 12. UserList — listas personalizadas
- 13. UserDict — diccionarios personalizados
- 📈 Comparación de memoria y rendimiento
- 1. Memoria:
listvstuplevsarray.array - 2. Velocidad de acceso:
listvstuplevsarray.array - 3. Memoria:
dictvsSimpleNamespacevsdataclass - 4. Optimización de memoria:
dataclasscon__slots__ - 5. Velocidad de búsqueda:
listvsset - 6. Memoria:
setvsfrozenset - 7. Velocidad de añadir:
list.appendvsdeque.appendvsdeque.appendleft
- 1. Memoria:
- 🧠 Recomendaciones de rendimiento
- 📊 Comparación de colecciones
- 💡 ¿Cuándo usar qué?
Lo que NO es una colección
Los siguientes tipos no son colecciones, ya que no contienen grupos de elementos:
int,float,bool— valores escalaresNone— ausencia de valor- funciones, módulos, clases — son objetos, pero no contenedores de datos (a menos que contengan
__dict__)
Colecciones integradas
Disponibles sin importar nada:
| Tipo | Descripción |
|---|---|
list | Secuencia ordenada, mutable. |
tuple | Secuencia ordenada, inmutable. |
dict | Mapeo clave-valor ordenado (desde Python 3.7). |
set | Colección no ordenada de elementos únicos. |
frozenset | Versión inmutable de set. |
Colecciones extendidas de la biblioteca estándar
| Tipo | Módulo | Propósito |
|---|---|---|
SimpleNamespace | types | Objeto con atributos dinámicos (alternativa al dict con acceso por .). |
namedtuple | collections | Tupla inmutable con campos nombrados. |
deque | collections | Cola de doble extremo — eficiente para añadir/eliminar en ambos extremos. |
Counter | collections | Subclase de dict para contar objetos hashables. |
defaultdict | collections | Diccionario con valores predeterminados para claves faltantes. |
dataclass | dataclasses | Genera automáticamente __init__, __repr__, __eq__, etc. |
UserList | collections | Clase base para objetos tipo lista personalizados. |
UserDict | collections | Clase base para objetos tipo diccionario personalizados. |
Otros tipos similares a colecciones
Aunque no siempre se les llama «colecciones», estos tipos también representan o almacenan grupos de datos.
1. str — cadena de caracteres
Secuencia ordenada, inmutable de caracteres.
s = "Python"
print(len(s)) # → 6
print(s[0]) # → P
print('y' in s) # → True
print(list(s)) # → ['P', 'y', 't', 'h', 'o', 'n']
2. bytes, bytearray
bytes— secuencia inmutable de bytes.bytearray— versión mutable.
b = b"hola"
print(b[0]) # → 104
print(len(b)) # → 4
ba = bytearray(b"hola")
ba[0] = 72
print(ba) # → bytearray(b'Hola')
3. range
Secuencia numérica perezosa, ordenada. No almacena los elementos en memoria.
r = range(3)
print(list(r)) # → [0, 1, 2]
print(1 in r) # → True
print(r[2]) # → 2
4. array.array
Almacena datos numéricos homogéneos de forma compacta (como en C).
from array import array
arr = array('i', [1, 2, 3]) # 'i' = entero con signo
print(arr) # → array('i', [1, 2, 3])
5. Generadores e iteradores
No almacenan datos — los generan bajo demanda. No admiten len() ni indexación.
gen = (x * 2 for x in range(3))
print(list(gen)) # → [0, 2, 4]
# len(gen) → TypeError
6. ChainMap (de collections)
Agrupa varios diccionarios en una sola vista — la búsqueda recorre los mapas en orden.
from collections import ChainMap
d1 = {'a': 1}
d2 = {'b': 2}
cm = ChainMap(d1, d2)
print(cm['a']) # → 1
print(cm['b']) # → 2
7. OrderedDict (de collections)
Diccionario que recuerda el orden de inserción. Relevante para Python < 3.7.
from collections import OrderedDict
od = OrderedDict([('a', 1), ('b', 2)])
print(od) # → OrderedDict([('a', 1), ('b', 2)])
8. enum.Enum, enum.Flag
Colecciones de constantes con nombre.
from enum import Enum
class Color(Enum):
ROJO = 1
VERDE = 2
print(list(Color)) # → [<Color.ROJO: 1>, <Color.VERDE: 2>]
9. typing.NamedTuple, typing.TypedDict
Envoltorios tipados sobre namedtuple y dict.
from typing import NamedTuple, TypedDict
class Persona(NamedTuple):
nombre: str
edad: int
p = Persona("Sofía", 25)
class Pelicula(TypedDict):
titulo: str
año: int
m: Pelicula = {"titulo": "Matrix", "año": 1999}
10. heapq, bisect — herramientas, no colecciones
Trabajan con colecciones, pero no lo son:
heapq— algoritmo de cola de prioridad mediante listas.bisect— mantiene el orden en listas ordenadas.
1. Listas — list
Colección ordenada, mutable. Los elementos pueden repetirse, se permiten todos los tipos.
Se usa cuando se necesita una secuencia flexible: añadir, eliminar, modificar elementos.
Creación: []
carlos_list = ["Carlos", "Madrid", 30, "ingeniero"]
print(f"Creación de lista: {carlos_list}")
# → Creación de lista: ['Carlos', 'Madrid', 30, 'ingeniero']
print(f"Elemento en índice 0: {carlos_list[0]}")
# → Elemento en índice 0: Carlos
carlos_list[2] = 31
print(f"Después de modificación: {carlos_list}")
# → Después de modificación: ['Carlos', 'Madrid', 31, 'ingeniero']
carlos_list.append("casado")
print(f"Después de append: {carlos_list}")
# → Después de append: ['Carlos', 'Madrid', 31, 'ingeniero', 'casado']
carlos_list.insert(1, "España")
print(f"Después de insert: {carlos_list}")
# → Después de insert: ['Carlos', 'España', 'Madrid', 31, 'ingeniero', 'casado']
carlos_list.remove("ingeniero")
print(f"Después de remove por valor: {carlos_list}")
# → Después de remove por valor: ['Carlos', 'España', 'Madrid', 31, 'casado']
del carlos_list[2]
print(f"Después de borrar por índice: {carlos_list}")
# → Después de borrar por índice: ['Carlos', 'España', 31, 'casado']
carlos_list.extend(["aficiones", "pesca"])
print(f"Después de extend: {carlos_list}")
# → Después de extend: ['Carlos', 'España', 31, 'casado', 'aficiones', 'pesca']
carlos_list.pop()
print(f"Después de pop: {carlos_list}")
# → Después de pop: ['Carlos', 'España', 31, 'casado', 'aficiones']
2. Diccionarios — dict
Colección de pares clave → valor. Las claves deben ser hashables. Desde Python 3.7, se conserva el orden de inserción.
Útil para datos estructurados: perfiles, configuraciones, JSON.
Creación: {}
sofia_dict = {"nombre": "Sofía", "edad": 25, "ciudad": "Barcelona", "profesión": "artista"}
print(f"Creación de dict: {sofia_dict}")
# → Creación de dict: {'nombre': 'Sofía', 'edad': 25, 'ciudad': 'Barcelona', 'profesión': 'artista'}
print(f"Valor por clave 'nombre': {sofia_dict['nombre']}")
# → Valor por clave 'nombre': Sofía
sofia_dict["edad"] = 26
print(f"Después de actualización: {sofia_dict}")
# → Después de actualización: {'nombre': 'Sofía', 'edad': 26, 'ciudad': 'Barcelona', 'profesión': 'artista'}
sofia_dict["afición"] = "pintura"
print(f"Después de añadir par: {sofia_dict}")
# → Después de añadir par: {'nombre': 'Sofía', 'edad': 26, 'ciudad': 'Barcelona', 'profesión': 'artista', 'afición': 'pintura'}
del sofia_dict["ciudad"]
print(f"Después de borrar par: {sofia_dict}")
# → Después de borrar par: {'nombre': 'Sofía', 'edad': 26, 'profesión': 'artista', 'afición': 'pintura'}
afición = sofia_dict.pop("afición")
print(f"Después de pop: {sofia_dict}, valor: {afición}")
# → Después de pop: {'nombre': 'Sofía', 'edad': 26, 'profesión': 'artista'}, valor: pintura
print(f"Clave 'nombre' existe: {'nombre' in sofia_dict}")
# → Clave 'nombre' existe: True
3. Tuplas — tuple
Colección ordenada, inmutable. Adecuada para datos fijos.
Se usa cuando la inmutabilidad es importante: coordenadas, parámetros, valores de retorno.
Creación: ()
carlos_tuple = ("Carlos", "Madrid", 30, "ingeniero")
print(f"Creación de tuple: {carlos_tuple}")
# → Creación de tuple: ('Carlos', 'Madrid', 30, 'ingeniero')
print(f"Elemento en índice 2: {carlos_tuple[2]}")
# → Elemento en índice 2: 30
# carlos_tuple[0] = "Pedro" → TypeError
# carlos_tuple.append("algo") → AttributeError
- Las tuplas consumen menos memoria y son más rápidas que las listas.
- Ideal cuando no se necesita mutabilidad.
4. SimpleNamespace
Clase simple de types para crear objetos con atributos dinámicos. Acceso mediante notación de punto (obj.attr).
Útil cuando se quiere sintaxis obj.nombre sin definir una clase completa.
from types import SimpleNamespace
sofia_ns = SimpleNamespace(nombre="Sofía", edad=25, ciudad="Barcelona")
print(f"Objeto: {sofia_ns}")
# → Objeto: namespace(nombre='Sofía', edad=25, ciudad='Barcelona')
print(f"Nombre: {sofia_ns.nombre}")
# → Nombre: Sofía
sofia_ns.edad = 26
print(f"Después de actualización: {sofia_ns}")
# → Después de actualización: namespace(nombre='Sofía', edad=26, ciudad='Barcelona')
sofia_ns.profesión = "artista"
print(f"Con nuevo atributo: {sofia_ns}")
# → Con nuevo atributo: namespace(nombre='Sofía', edad=26, ciudad='Barcelona', profesión='artista')
del sofia_ns.ciudad
print(f"Después de borrado: {sofia_ns}")
# → Después de borrado: namespace(nombre='Sofía', edad=26, profesión='artista')
setattr(sofia_ns, "afición", "pintura")
print(f"Vía setattr: {sofia_ns}")
# → Vía setattr: namespace(nombre='Sofía', edad=26, profesión='artista', afición='pintura')
delattr(sofia_ns, "afición")
print(f"Vía delattr: {sofia_ns}")
# → Vía delattr: namespace(nombre='Sofía', edad=26, profesión='artista')
- Alternativa al dict cuando
obj.nombrees preferible aobj['nombre'].
5. Conjuntos — set
Colección no ordenada de elementos únicos. Admite operaciones de conjunto: unión, intersección, diferencia.
Se usa para eliminar duplicados y verificar pertenencia.
Creación: {} o set()
numeros = {1, 2, 3, 3, 2, 1}
print(f"Conjunto: {numeros}")
# → Conjunto: {1, 2, 3}
numeros.add(4)
print(f"Después de añadir: {numeros}")
# → Después de añadir: {1, 2, 3, 4}
numeros.remove(2)
print(f"Después de borrar: {numeros}")
# → Después de borrar: {1, 3, 4}
otro = {3, 4, 5}
print(f"Unión: {numeros | otro}")
# → Unión: {1, 3, 4, 5}
print(f"Intersección: {numeros & otro}")
# → Intersección: {3, 4}
print(f"Diferencia: {numeros - otro}")
# → Diferencia: {1}
6. Conjuntos inmutables — frozenset
Versión inmutable de set. Puede usarse como clave de dict o elemento de otro conjunto.
frozen = frozenset([1, 2, 3, 2])
print(f"frozenset: {frozen}")
# → frozenset: frozenset({1, 2, 3})
otro = frozenset([3, 4])
print(f"Intersección: {frozen & otro}")
# → Intersección: frozenset({3})
print(f"Unión: {frozen | otro}")
# → Unión: frozenset({1, 2, 3, 4})
# frozen.add(5) → AttributeError
7. namedtuple — tuplas con nombre
Estructura inmutable con acceso por nombre de campo. Más legible que las tuplas comunes.
from collections import namedtuple
Persona = namedtuple("Persona", ["nombre", "edad", "ciudad"])
sofia = Persona("Sofía", 25, "Barcelona")
print(f"Objeto: {sofia}")
# → Objeto: Persona(nombre='Sofía', edad=25, ciudad='Barcelona')
print(f"Nombre: {sofia.nombre}")
# → Nombre: Sofía
print(f"Edad: {sofia[1]}")
# → Edad: 25
# sofia.edad = 26 → AttributeError
sofia_nueva = sofia._replace(edad=26)
print(f"Copia modificada: {sofia_nueva}")
# → Copia modificada: Persona(nombre='Sofía', edad=26, ciudad='Barcelona')
- Ideal para registros: puntos, usuarios, configuraciones — cuando importan inmutabilidad y legibilidad.
8. deque — cola de doble extremo
Optimizada para añadir/eliminar rápidamente en ambos extremos. Más eficiente que list para appendleft, popleft.
from collections import deque
d = deque([1, 2, 3])
print(f"deque inicial: {d}")
# → deque inicial: deque([1, 2, 3])
d.appendleft(0)
print(f"Después de appendleft: {d}")
# → Después de appendleft: deque([0, 1, 2, 3])
d.append(4)
print(f"Después de append: {d}")
# → Después de append: deque([0, 1, 2, 3, 4])
izquierda = d.popleft()
print(f"Después de popleft: {izquierda}, restante: {d}")
# → Después de popleft: 0, restante: deque([1, 2, 3, 4])
derecha = d.pop()
print(f"Después de pop: {derecha}, restante: {d}")
# → Después de pop: 4, restante: deque([1, 2, 3])
- Usado en algoritmos: BFS, cachés LRU, buffers — cuando las operaciones en extremos deben ser rápidas.
9. Counter — contador de elementos
Cuenta la frecuencia de elementos en un iterable. Útil para estadísticas y análisis.
from collections import Counter
texto = "abracadabra"
c = Counter(texto)
print(f"Conteo de letras: {c}")
# → Conteo de letras: Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
print(f"Frecuencia de 'a': {c['a']}")
# → Frecuencia de 'a': 5
print(f"Top 3: {c.most_common(3)}")
# → Top 3: [('a', 5), ('b', 2), ('r', 2)]
c2 = Counter("bukva")
c.update(c2)
print(f"Después de update: {c}")
# → Después de update: Counter({'a': 6, 'b': 3, 'r': 2, 'c': 1, 'd': 1, 'u': 1, 'k': 1, 'v': 1})
- Útil para análisis de texto, logs, votaciones — donde se necesita contar «lo que aparece más a menudo».
10. defaultdict — diccionario con valores por defecto
Crea automáticamente valores por defecto para claves faltantes. Elimina verificaciones if key in dict.
from collections import defaultdict
dd_list = defaultdict(list)
dd_list["frutas"].append("manzana")
dd_list["frutas"].append("plátano")
print(f"Lista: {dict(dd_list)}")
# → Lista: {'frutas': ['manzana', 'plátano']}
dd_int = defaultdict(int)
for char in "abracadabra":
dd_int[char] += 1
print(f"Conteos: {dict(dd_int)}")
# → Conteos: {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
dd_set = defaultdict(set)
dd_set["ciudades"].add("Madrid")
dd_set["ciudades"].add("Barcelona")
print(f"Conjunto: {dict(dd_set)}")
# → Conjunto: {'ciudades': {'Madrid', 'Barcelona'}}
- Elimina código repetitivo como
if key not in d: d[key] = []. - Hace el código más limpio y seguro.
11. dataclass — clases de datos
Decorador que genera automáticamente __init__, __repr__, __eq__, etc.
from dataclasses import dataclass
@dataclass
class Persona:
nombre: str
edad: int
ciudad: str = "No especificada"
sofia = Persona("Sofía", 25)
print(f"Objeto: {sofia}")
# → Objeto: Persona(nombre='Sofía', edad=25, ciudad='No especificada')
print(f"Nombre: {sofia.nombre}")
# → Nombre: Sofía
sofia.edad = 26
print(f"Después de actualización: {sofia}")
# → Después de actualización: Persona(nombre='Sofía', edad=26, ciudad='No especificada')
bob = Persona("Bob", 30)
print(f"Sofía == Bob: {sofia == bob}")
# → Sofía == Bob: False
@dataclass(frozen=True)
class PersonaInmutable:
nombre: str
edad: int
ivan = PersonaInmutable("Iván", 40)
# ivan.edad = 41 → FrozenInstanceError
- Reemplaza la escritura manual de
__init__,__repr__,__eq__. - Ideal para DTOs, configuraciones, modelos.
12. UserList — listas personalizadas
Hereda de collections.UserList. Se usa para crear listas con comportamiento personalizado.
from collections import UserList
class ListaConLogs(UserList):
def append(self, item):
print(f"[LOG] Añadir: {item}")
super().append(item)
def remove(self, item):
print(f"[LOG] Borrar: {item}")
super().remove(item)
log_list = ListaConLogs([1, 2, 3])
print(f"Inicial: {log_list}")
# → Inicial: [1, 2, 3]
log_list.append(4)
# → [LOG] Añadir: 4
print(f"Después de append: {log_list}")
# → Después de append: [1, 2, 3, 4]
log_list.remove(2)
# → [LOG] Borrar: 2
print(f"Después de remove: {log_list}")
# → Después de remove: [1, 3, 4]
- Útil para añadir logs, validaciones, o modificar el comportamiento estándar de listas.
13. UserDict — diccionarios personalizados
Hereda de collections.UserDict. Se usa para crear dicts con comportamiento personalizado.
from collections import UserDict
class DictClavesMinusculas(UserDict):
def __setitem__(self, key, value):
key = key.lower() if isinstance(key, str) else key
super().__setitem__(key, value)
def __getitem__(self, key):
key = key.lower() if isinstance(key, str) else key
return super().__getitem__(key)
ld = DictClavesMinusculas()
ld["Nombre"] = "Sofía"
print(f"Valor por 'Nombre': {ld['Nombre']}")
# → Valor por 'Nombre': Sofía
print(f"Valor por 'nombre': {ld['nombre']}")
# → Valor por 'nombre': Sofía
print(f"Claves: {list(ld.keys())}")
# → Claves: ['nombre']
- Se usa para normalizar claves, validar, registrar, cachear, etc.
📈 Comparación de memoria y rendimiento
La elección de la colección afecta rendimiento y uso de memoria. A continuación, benchmarks prácticos.
1. Memoria: list vs tuple vs array.array
import sys
from array import array
n = 1_000_000
data = list(range(n))
data_t = tuple(range(n))
data_a = array('i', range(n))
print(f"list: {sys.getsizeof(data) / 1024 / 1024:.2f} MB")
# → list: 8.00 MB
print(f"tuple: {sys.getsizeof(data_t) / 1024 / 1024:.2f} MB")
# → tuple: 8.00 MB
print(f"array: {sys.getsizeof(data_a) / 1024 / 1024:.2f} MB")
# → array: 3.81 MB
array.arrayusa ~2x menos memoria para números.listytupleconsumen memoria similar, perotuplees ligeramente más rápido en iteración.
2. Velocidad de acceso: list vs tuple vs array.array
import time
def time_access(collection, name):
start = time.perf_counter()
total = 0
for i in range(len(collection)):
total += collection[i]
end = time.perf_counter()
print(f"{name}: {end - start:.4f} segundos")
n = 10_000_000
lst = list(range(n))
tpl = tuple(range(n))
arr = array('i', range(n))
time_access(lst, "list") # → list: 1.2000 segundos
time_access(tpl, "tuple") # → tuple: 1.0000 segundos
time_access(arr, "array") # → array: 0.8000 segundos
array.arrayes el más rápido para datos numéricos.tuplees 10–20% más rápido quelist.- La diferencia es notable a gran escala.
3. Memoria: dict vs SimpleNamespace vs dataclass
d = {"nombre": "A", "edad": 25, "ciudad": "X", "afición": "Y", "trabajo": "Z"}
ns = SimpleNamespace(nombre="A", edad=25, ciudad="X", afición="Y", trabajo="Z")
dc = PersonaDC("A", 25, "X", "Y", "Z")
print(f"dict: {sys.getsizeof(d)} bytes") # → 232
print(f"SimpleNamespace: {sys.getsizeof(ns)} bytes") # → 64
print(f"dataclass: {sys.getsizeof(dc)} bytes") # → 64
print(f"ns.__dict__: {sys.getsizeof(ns.__dict__)} bytes") # → 232
SimpleNamespaceydataclassconsumen tanta memoria comodictdebido a__dict__.- Usa
__slots__para ahorrar memoria.
4. Optimización de memoria: dataclass con __slots__
@dataclass
class PersonaSlots:
__slots__ = ("nombre", "edad", "ciudad", "afición", "trabajo")
nombre: str
edad: int
ciudad: str
afición: str
trabajo: str
dc_slots = PersonaSlots("A", 25, "X", "Y", "Z")
print(f"dataclass + slots: {sys.getsizeof(dc_slots)} bytes")
# → 80 bytes
# dc_slots.nuevo = "valor" → AttributeError
__slots__ahorra memoria y acelera el acceso a atributos.- Contra: no se pueden añadir atributos dinámicamente.
5. Velocidad de búsqueda: list vs set
n = 1_000_000
lst = list(range(n))
st = set(range(n))
def time_in(collection, target, name):
start = time.perf_counter()
for _ in range(1000):
_ = target in collection
end = time.perf_counter()
print(f"{name} (búsqueda {target}): {end - start:.4f} segundos")
time_in(lst, 999_999, "list") # → 10.0000 segundos
time_in(st, 999_999, "set") # → 0.0005 segundos
setes miles de veces más rápido quelistpara verificación de pertenencia.- Siempre usa
setpara verificaciones frecuentes dex in collection.
6. Memoria: set vs frozenset
s = set(range(1000))
fs = frozenset(range(1000))
print(f"set: {sys.getsizeof(s)} bytes") # → 32792
print(f"frozenset: {sys.getsizeof(fs)} bytes") # → 32792
frozensetysetconsumen idéntica memoria.- La diferencia es solo la mutabilidad.
7. Velocidad de añadir: list.append vs deque.append vs deque.appendleft
from collections import deque
import time
def time_append(collection, n, method='append'):
start = time.perf_counter()
for i in range(n):
if method == 'appendleft' and hasattr(collection, 'appendleft'):
collection.appendleft(i)
else:
collection.append(i)
end = time.perf_counter()
return end - start
n = 100_000
lst = []
dq = deque()
time_list_append = time_append(lst, n) # → 0.0100 segundos
time_deque_append = time_append(dq, n) # → 0.0100 segundos
time_deque_appendleft = time_append(deque(), n, 'appendleft') # → 0.0100 segundos
# list.insert(0):
lst = []
start = time.perf_counter()
for i in range(n):
lst.insert(0, i)
end = time.perf_counter()
print(f"list.insert(0): {end - start:.4f} segundos") # → 5.0000 segundos
deque.appendleftes O(1), a diferencia delist.insert(0)que es O(n).- Usa
dequepara operaciones frecuentes en ambos extremos.
🧠 Recomendaciones de rendimiento
| Situación | Usar | Razón |
|---|---|---|
| Almacenar números, memoria crítica | array.array | 2x menos memoria, acceso más rápido |
| Datos inmutables | tuple | Más rápido que list, más seguro |
Verificaciones frecuentes x in collection | set / frozenset | O(1) vs O(n) de list |
| Operaciones en ambos extremos | deque | appendleft/popleft en O(1) |
| Datos estructurados, memoria crítica | dataclass + __slots__ | Sin __dict__, menos memoria |
| Contar frecuencias | Counter | Optimizado para esta tarea |
| Comportamiento personalizado | UserList / UserDict | Extensión segura de colecciones integradas |
📊 Comparación de colecciones
| Tipo | Ordenado | Mutable | Elementos únicos | Acceso por índice | Duplicados |
|---|---|---|---|---|---|
list | ✅ Sí | ✅ Sí | ❌ No | ✅ Sí | ✅ Sí |
tuple | ✅ Sí | ❌ No | ❌ No | ✅ Sí | ✅ Sí |
dict | ✅ Sí* | ✅ Sí | Solo claves | ❌ No | Valores: ✅ |
set | ❌ No | ✅ Sí | ✅ Sí | ❌ No | ❌ No |
frozenset | ❌ No | ❌ No | ✅ Sí | ❌ No | ❌ No |
SimpleNamespace | ✅ Sí (attrs) | ✅ Sí | ❌ No (attrs pueden repetirse semánticamente) | ❌ No | ✅ Sí |
namedtuple | ✅ Sí | ❌ No | ❌ No | ✅ Sí | ✅ Sí |
deque | ✅ Sí | ✅ Sí | ❌ No | ✅ Sí | ✅ Sí |
Counter | ❌ No | ✅ Sí | ❌ No | ❌ No (pero tiene claves) | ✅ Sí |
defaultdict | ✅ Sí* | ✅ Sí | Solo claves | ❌ No | Valores: ✅ |
dataclass | ✅ Sí (campos) | ✅ Sí (si no frozen) | ❌ No | ❌ No | ✅ Sí |
UserList | ✅ Sí | ✅ Sí | ❌ No | ✅ Sí | ✅ Sí |
UserDict | ✅ Sí* | ✅ Sí | Solo claves | ❌ No | Valores: ✅ |
str | ✅ Sí | ❌ No | ❌ No | ✅ Sí | ✅ Sí |
bytes | ✅ Sí | ❌ No | ❌ No | ✅ Sí | ✅ Sí |
bytearray | ✅ Sí | ✅ Sí | ❌ No | ✅ Sí | ✅ Sí |
range | ✅ Sí | ❌ No | ❌ No | ✅ Sí | ❌ No |
array.array | ✅ Sí | ✅ Sí | ❌ No | ✅ Sí | ✅ Sí |
ChainMap | ✅ Sí* | ✅ Sí | Solo claves | ❌ No | Valores: ✅ |
Enum | ✅ Sí | ❌ No | ✅ Sí (miembros) | ❌ No | ❌ No |
- — desde Python 3.7,
dict,defaultdict,UserDict,ChainMapconservan orden de inserción.
💡 ¿Cuándo usar qué?
| Tarea | Colección |
|---|---|
| Secuencia mutable | list / deque / UserList / bytearray |
| Datos inmutables | tuple / namedtuple / frozenset / str / bytes |
| Búsqueda rápida, eliminar duplicados | set / frozenset |
| Datos estructurados | dict / dataclass / SimpleNamespace / UserDict / TypedDict |
| Usar como clave de dict | frozenset |
Objetos temporales con acceso por . | SimpleNamespace / dataclass |
| Contar frecuencias | Counter |
| Valores por defecto para claves | defaultdict |
| Operaciones eficientes en extremos | deque |
| Comportamiento personalizado de lista | UserList |
| Comportamiento personalizado de dict | UserDict |
| Datos binarios | bytes / bytearray / array.array |
| Configuraciones con jerarquía | ChainMap |
| Constantes con nombre | Enum |
| Secuencias perezosas | range / generadores |