Saltar al contenido
> 💻 🧠 Código 1001 > 📚 Materiales de Aprendizaje > 🐍 Python > 📘 Colecciones en Python

📘 Colecciones en Python

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

Los siguientes tipos no son colecciones, ya que no contienen grupos de elementos:

  • int, float, bool — valores escalares
  • None — 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:

TipoDescripción
listSecuencia ordenada, mutable.
tupleSecuencia ordenada, inmutable.
dictMapeo clave-valor ordenado (desde Python 3.7).
setColección no ordenada de elementos únicos.
frozensetVersión inmutable de set.

Colecciones extendidas de la biblioteca estándar

TipoMóduloPropósito
SimpleNamespacetypesObjeto con atributos dinámicos (alternativa al dict con acceso por .).
namedtuplecollectionsTupla inmutable con campos nombrados.
dequecollectionsCola de doble extremo — eficiente para añadir/eliminar en ambos extremos.
CountercollectionsSubclase de dict para contar objetos hashables.
defaultdictcollectionsDiccionario con valores predeterminados para claves faltantes.
dataclassdataclassesGenera automáticamente __init__, __repr__, __eq__, etc.
UserListcollectionsClase base para objetos tipo lista personalizados.
UserDictcollectionsClase 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.nombre es preferible a obj['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.array usa ~2x menos memoria para números.
  • list y tuple consumen memoria similar, pero tuple es 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.array es el más rápido para datos numéricos.
  • tuple es 10–20% más rápido que list.
  • 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
  • SimpleNamespace y dataclass consumen tanta memoria como dict debido 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
  • set es miles de veces más rápido que list para verificación de pertenencia.
  • Siempre usa set para verificaciones frecuentes de x 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
  • frozenset y set consumen 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.appendleft es O(1), a diferencia de list.insert(0) que es O(n).
  • Usa deque para operaciones frecuentes en ambos extremos.

🧠 Recomendaciones de rendimiento

SituaciónUsarRazón
Almacenar números, memoria críticaarray.array2x menos memoria, acceso más rápido
Datos inmutablestupleMás rápido que list, más seguro
Verificaciones frecuentes x in collectionset / frozensetO(1) vs O(n) de list
Operaciones en ambos extremosdequeappendleft/popleft en O(1)
Datos estructurados, memoria críticadataclass + __slots__Sin __dict__, menos memoria
Contar frecuenciasCounterOptimizado para esta tarea
Comportamiento personalizadoUserList / UserDictExtensión segura de colecciones integradas

📊 Comparación de colecciones

TipoOrdenadoMutableElementos únicosAcceso por índiceDuplicados
list✅ Sí✅ Sí❌ No✅ Sí✅ Sí
tuple✅ Sí❌ No❌ No✅ Sí✅ Sí
dict✅ Sí*✅ SíSolo claves❌ NoValores: ✅
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❌ NoValores: ✅
dataclass✅ Sí (campos)✅ Sí (si no frozen)❌ No❌ No✅ Sí
UserList✅ Sí✅ Sí❌ No✅ Sí✅ Sí
UserDict✅ Sí*✅ SíSolo claves❌ NoValores: ✅
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❌ NoValores: ✅
Enum✅ Sí❌ No✅ Sí (miembros)❌ No❌ No
  • — desde Python 3.7, dict, defaultdict, UserDict, ChainMap conservan orden de inserción.

💡 ¿Cuándo usar qué?

TareaColección
Secuencia mutablelist / deque / UserList / bytearray
Datos inmutablestuple / namedtuple / frozenset / str / bytes
Búsqueda rápida, eliminar duplicadosset / frozenset
Datos estructuradosdict / dataclass / SimpleNamespace / UserDict / TypedDict
Usar como clave de dictfrozenset
Objetos temporales con acceso por .SimpleNamespace / dataclass
Contar frecuenciasCounter
Valores por defecto para clavesdefaultdict
Operaciones eficientes en extremosdeque
Comportamiento personalizado de listaUserList
Comportamiento personalizado de dictUserDict
Datos binariosbytes / bytearray / array.array
Configuraciones con jerarquíaChainMap
Constantes con nombreEnum
Secuencias perezosasrange / generadores

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *