Tipos de Datos Integrados
Domina los fundamentos: números, secuencias, conjuntos y diccionarios
"¡Datos! ¡Datos! ¡Datos!" gritó impaciente. "No puedo hacer ladrillos sin arcilla." — Sherlock Holmes
Todo lo que haces con una computadora es gestionar datos. Los datos vienen en muchas formas y sabores: la música que escuchas, las películas que transmites, los PDFs que abres. Python ofrece una variedad asombrosa de estructuras de datos que puedes usar para representar información o combinarlas para crear tus propias estructuras personalizadas.
En este artículo exploraremos los tipos de datos integrados de Python: números, cadenas, secuencias, conjuntos, diccionarios y más.
Todo es un Objeto
En Python, absolutamente todo es un objeto, y cada objeto tiene una identidad (id), un tipo y un valor. Pero, ¿qué sucede realmente cuando escribes una instrucción como age = 42?
Se crea un objeto que obtiene un id, el tipo se establece como int, y el valor como 42. Un nombre, age, se coloca en el namespace global, apuntando a ese objeto.
>>> age = 42 >>> id(age) 4377553168 >>> type(age) <class 'int'> >>> age 42
Mutabilidad vs Inmutabilidad
La primera distinción fundamental que Python hace sobre los datos es si el valor de un objeto puede cambiar. Si el valor puede cambiar, el objeto se llama mutable; de lo contrario, es inmutable.
# Inmutable: int >>> age = 42 >>> id(age) 4377553168 >>> age = 43 # Se crea un NUEVO objeto >>> id(age) 4377553200 # ¡ID diferente! # Mutable: objeto personalizado >>> class Person: ... def __init__(self, age): ... self.age = age ... >>> fab = Person(age=48) >>> id(fab) 4380878496 >>> fab.age = 25 # ¡Ojalá! >>> id(fab) 4380878496 # ¡Mismo ID!
int, cuando "cambias" el valor, realmente creas un nuevo objeto. Con objetos mutables, el mismo objeto puede modificarse sin cambiar su identidad.
Números
Python fue diseñado por alguien con maestría en matemáticas y ciencias de la computación, así que tiene soporte extensivo para números. Los números son objetos inmutables.
Enteros (int)
Los enteros en Python tienen un rango ilimitado, sujeto solo a la memoria virtual disponible. Soportan todas las operaciones matemáticas básicas.
>>> a = 14 >>> b = 3 >>> a + b # suma 17 >>> a - b # resta 11 >>> a * b # multiplicación 42 >>> a / b # división verdadera 4.666666666666667 >>> a // b # división entera (floor) 4 >>> a % b # módulo (residuo) 2 >>> a ** b # potencia 2744 # Python maneja números ENORMES >>> 2 ** 1024 17976931348623159077293051907890247336179769789...
1_000_000_000 es equivalente a 1000000000.
Booleanos (bool)
Los booleanos son una subclase de enteros. True y False se comportan como 1 y 0 respectivamente.
>>> int(True) # True se comporta como 1 1 >>> int(False) # False se comporta como 0 0 >>> bool(42) # cualquier número no-cero es True True >>> bool(0) # cero es False False # Operadores lógicos >>> not True False >>> True and True True >>> False or True True # ¡Puedes sumarlos! >>> 1 + True 2
Números Reales (float)
Los números de punto flotante se representan según el formato IEEE 754 de doble precisión (64 bits).
>>> pi = 3.1415926536 >>> radius = 4.5 >>> area = pi * (radius ** 2) >>> area 63.617251235400005 # ¡CUIDADO con la precisión! >>> 0.3 - 0.1 * 3 # debería ser 0 -5.551115123125783e-17 # ¡aproximación!
Fracciones y Decimales
Para precisión exacta (especialmente en cálculos financieros), usa Fraction o Decimal.
>>> from fractions import Fraction >>> Fraction(10, 6) Fraction(5, 3) # ¡simplificado automáticamente! >>> from decimal import Decimal as D >>> D("0.1") * D(3) - D("0.3") Decimal('0.0') # ¡Precisión perfecta!
Decimal con strings para evitar problemas de aproximación.
Secuencias Inmutables
Strings (str)
Los datos textuales se manejan con objetos str. Son secuencias inmutables de puntos de código Unicode.
# 4 formas de crear strings >>> str1 = 'Comillas simples' >>> str2 = "Comillas dobles" >>> str3 = '''Comillas triples ... para múltiples líneas.''' >>> str4 = """También con ... comillas dobles triples.""" >>> len(str1) # longitud 16 # Nuevos métodos Python 3.9+ >>> s = "Hello There" >>> s.removeprefix("Hell") 'o There' >>> s.removesuffix("here") 'Hello T'
Indexación y Slicing
| H | e | l | l | o | T | h | e | r | e |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| -10 | -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |
>>> s = "The trouble is you think you have time." >>> s[0] # primer carácter 'T' >>> s[-1] # último carácter '.' >>> s[:4] # primeros 4 caracteres 'The ' >>> s[4:] # desde posición 4 hasta el final 'trouble is you think you have time.' >>> s[2:14] # desde pos 2 hasta 14 (exclusivo) 'e trouble is' >>> s[2:14:3] # con paso de 3 'erb ' >>> s[::-1] # ¡string invertido! '.emit evah uoy kniht uoy si elbuort ehT'
F-Strings (Formatted String Literals)
>>> name = "Fab" >>> age = 48 >>> f"Hello! My name is {name} and I'm {age}" "Hello! My name is Fab and I'm 48" # Python 3.8+: especificador = >>> user = "heinrich" >>> f"Log in with: {user=}" "Log in with: user='heinrich'" # Python 3.12+: reutilización de comillas >>> languages = ["Python", "JavaScript"] >>> f"Languages: {", ".join(languages)}" 'Languages: Python, JavaScript'
Tuplas (tuple)
Una tupla es una secuencia de objetos Python arbitrarios. Son inmutables y pueden usarse como claves de diccionario.
>>> t = () # tupla vacía >>> one_element = (42,) # ¡necesitas la coma! >>> triple = (1, 3, 5) # paréntesis opcionales # Asignación múltiple >>> a, b, c = 1, 2, 3 >>> a, b, c (1, 2, 3) # Intercambio Pythónico (sin variable temporal) >>> a, b = 0, 1 >>> a, b = b, a # ¡magia! >>> a, b (1, 0) # Membership test >>> 3 in triple True
Secuencias Mutables
Listas (list)
Las listas son similares a las tuplas pero sin las restricciones de inmutabilidad. Son la estructura de datos más versátil de Python.
>>> [] # lista vacía >>> list() # equivalente >>> [1, 2, 3] # lista literal >>> [x + 5 for x in [2, 3, 4]] # ¡list comprehension! [7, 8, 9] >>> list("hello") # desde string ['h', 'e', 'l', 'l', 'o']
Métodos Principales de Listas
>>> a = [1, 2, 1, 3] >>> a.append(13) # añadir al final >>> a [1, 2, 1, 3, 13] >>> a.count(1) # contar ocurrencias 2 >>> a.extend([5, 7]) # extender con otra secuencia >>> a [1, 2, 1, 3, 13, 5, 7] >>> a.index(13) # posición del elemento 4 >>> a.insert(0, 17) # insertar en posición >>> a [17, 1, 2, 1, 3, 13, 5, 7] >>> a.pop() # remover y retornar el último 7 >>> a.remove(17) # remover por valor >>> a.reverse() # invertir in-place >>> a.sort() # ordenar in-place >>> a.clear() # vaciar la lista
Operaciones Comunes
>>> a = [1, 3, 5, 7] >>> min(a) # mínimo 1 >>> max(a) # máximo 7 >>> sum(a) # suma 16 >>> len(a) # longitud 4 from math import prod >>> prod(a) # producto (Python 3.8+) 105 # Operadores sobrecargados >>> b = [6, 7, 8] >>> a + b # concatenación [1, 3, 5, 7, 6, 7, 8] >>> a * 2 # repetición [1, 3, 5, 7, 1, 3, 5, 7]
Ordenamiento Avanzado
from operator import itemgetter >>> a = [(5, 3), (1, 3), (1, 2), (2, -1), (4, 9)] >>> sorted(a) # por defecto: ordena por tupla completa [(1, 2), (1, 3), (2, -1), (4, 9), (5, 3)] >>> sorted(a, key=itemgetter(0)) # solo por primer elemento [(1, 3), (1, 2), (2, -1), (4, 9), (5, 3)] >>> sorted(a, key=itemgetter(1)) # por segundo elemento [(2, -1), (1, 2), (5, 3), (1, 3), (4, 9)] >>> sorted(a, key=itemgetter(1), reverse=True) # descendente [(4, 9), (5, 3), (1, 3), (1, 2), (2, -1)]
Tipos de Conjuntos
Python proporciona dos tipos de conjuntos: set (mutable) y frozenset (inmutable). Son colecciones desordenadas de objetos inmutables hashables.
>>> small_primes = set() # conjunto vacío >>> small_primes.add(2) >>> small_primes.add(3) >>> small_primes.add(5) >>> small_primes {2, 3, 5} >>> small_primes.add(3) # duplicados ignorados >>> small_primes {2, 3, 5} # Membership test >>> 3 in small_primes True >>> 4 not in small_primes True # Operaciones de conjuntos >>> bigger_primes = {5, 7, 11, 13>>> small_primes | bigger_primes # unión {2, 3, 5, 7, 11, 13} >>> small_primes & bigger_primes # intersección {5} >>> small_primes - bigger_primes # diferencia {2, 3}
Diccionarios
El diccionario es el tipo de datos más interesante de Python. Es el único tipo de mapeo estándar y es el backbone de cada objeto Python. Mapea claves (hashables) a valores (cualquier tipo).
# 5 formas de crear el mismo diccionario >>> a = dict(A=1, Z=-1) >>> b = {"A": 1, "Z": -1} >>> c = dict(zip(["A", "Z"], [1, -1])) >>> d = dict([("A", 1), ("Z", -1)]) >>> e = dict({"Z": -1, "A": 1}) >>> a == b == c == d == e True
Operaciones Básicas
>>> d = {} >>> d["a"] = 1 # asignar >>> d["b"] = 2 >>> len(d) # número de pares 2 >>> d["a"] # acceder 1 >>> del d["a"] # eliminar >>> "b" in d # membership (solo claves) True # Vistas del diccionario >>> d = dict(zip("hello", range(5))) >>> d.keys() dict_keys(['h', 'e', 'l', 'o']) >>> d.values() dict_values([0, 1, 3, 4]) >>> d.items() dict_items([('h', 0), ('e', 1), ('l', 3), ('o', 4)])
Métodos Útiles
>>> d = {'h': 0, 'e': 1, 'l': 3, 'o': 4} >>> d.pop("l") # remover y retornar 3 >>> d.pop("x", "default") # con valor por defecto 'default' >>> d.get("h") # como d['h'] pero sin KeyError 0 >>> d.get("x", 99) # valor por defecto si no existe 99 >>> d.update({"new": 42}) # actualizar con otro dict >>> d.setdefault("a", 1) # establece si no existe 1 # Python 3.9+: operador de unión >>> d = {"a": "A", "b": "B"} >>> e = {"b": 8, "c": "C"} >>> d | e # unión (e sobrescribe) {'a': 'A', 'b': 8, 'c': 'C'}
None se usa frecuentemente para representar la ausencia de un valor. Cada función en Python retorna None a menos que explícitamente retorne otra cosa.
El Módulo Collections
Cuando los contenedores integrados no son suficientes, el módulo collections ofrece tipos de datos especializados.
| Tipo | Descripción |
|---|---|
| namedtuple() | Tuplas con campos nombrados |
| deque | Lista con append/pop rápido en ambos extremos |
| Counter | Diccionario para contar objetos hashables |
| defaultdict | Dict que llama una factory para valores faltantes |
| ChainMap | Vista única de múltiples mapeos |
namedtuple
from collections import namedtuple # Problema con tuplas normales >>> vision = (9.5, 8.8) >>> vision[0] # ¿qué ojo es este? 🤔 # Solución con namedtuple >>> Vision = namedtuple('Vision', ['left', 'right']) >>> vision = Vision(9.5, 8.8) >>> vision.left # ¡explícito! 9.5 >>> vision.right 8.8 >>> vision[0] # todavía funciona por índice 9.5
defaultdict
from collections import defaultdict # Sin defaultdict >>> d = {} >>> d["age"] = d.get("age", 0) + 1 # Con defaultdict >>> dd = defaultdict(int) # int() = 0 >>> dd["age"] += 1 # ¡más limpio! >>> dd defaultdict(<class 'int'>, {'age': 1})
ChainMap
from collections import ChainMap >>> default_conn = {'host': 'localhost', 'port': 4567} >>> custom_conn = {'port': 5678>>> conn = ChainMap(custom_conn, default_conn) >>> conn['port'] # encontrado en custom_conn 5678 >>> conn['host'] # encontrado en default_conn 'localhost'
Enumeraciones
Las enumeraciones son conjuntos de nombres simbólicos vinculados a valores únicos y constantes. Introducidas en Python 3.4.
from enum import Enum # Forma tradicional (no recomendada) >>> GREEN = 1 >>> YELLOW = 2 >>> RED = 4 # Con Enum (¡mucho mejor!) >>> class TrafficLight(Enum): ... GREEN = 1 ... YELLOW = 2 ... RED = 4 >>> TrafficLight.GREEN <TrafficLight.GREEN: 1> >>> TrafficLight.GREEN.name 'GREEN' >>> TrafficLight.GREEN.value 1 >>> TrafficLight(4) # acceso por valor <TrafficLight.RED: 4>
Consideraciones Finales
Caché de Valores Pequeños
Python utiliza object interning para optimizar memoria en objetos inmutables pequeños.
>>> a = 1000000 >>> b = 1000000 >>> id(a) == id(b) False # objetos diferentes >>> a = 5 >>> b = 5 >>> id(a) == id(b) True # ¡mismo objeto! (interning)
Cómo Elegir Estructuras de Datos
Resumen del Capítulo
01 // Objetos y Mutabilidad
Todo en Python es un objeto con id, tipo y valor. Los inmutables no pueden cambiar después de su creación.
02 // Números
int (ilimitado), float (64-bit), bool (True/False), complex, Fraction, Decimal para precisión.
03 // Secuencias
Inmutables: str, tuple, bytes. Mutables: list, bytearray. Soportan indexación y slicing.
04 // Conjuntos
set (mutable) y frozenset (inmutable). Operaciones: unión, intersección, diferencia.
05 // Diccionarios
Mapeo clave-valor. O(1) para acceso. El backbone de Python. Vistas: keys(), values(), items().
06 // Collections
namedtuple, defaultdict, Counter, deque, ChainMap para necesidades especializadas.