lunes, 19 de enero de 2026

Aprendiendo Python de 0 a experto - Tipos de Datos Integrados

Tipos de Datos Integrados en Python
Python // Capítulo 02

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.

TIPO_01

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?

Anatomía de un Objeto Python
name: age
——→
id: 4377553168
type: int
value: 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.

python_console
>>> 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, float, str, tuple, frozenset, bytes — El valor NO puede cambiar después de la creación
MUTABLE
list, dict, set, bytearray — El valor PUEDE cambiar sin crear un nuevo objeto
mutability_example.py
# 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!
Con objetos inmutables como int, cuando "cambias" el valor, realmente creas un nuevo objeto. Con objetos mutables, el mismo objeto puede modificarse sin cambiar su identidad.
TIPO_02

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.

integer_operations.py
>>> 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...
Python 3.6 introdujo la capacidad de añadir guiones bajos en literales numéricos para mejorar la legibilidad: 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.

boolean_examples.py
>>> 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).

float_examples.py
>>> 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.

precision_types.py
>>> 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!
Cuando se trata de precios o cálculos financieros, siempre usa Decimal con strings para evitar problemas de aproximación.
TIPO_03

Secuencias Inmutables

Strings (str)

Los datos textuales se manejan con objetos str. Son secuencias inmutables de puntos de código Unicode.

string_creation.py
# 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

Indexación en Python: "HelloThere"
HelloThere
0123456789
-10-9-8-7-6-5-4-3-2-1
slicing_examples.py
>>> 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)

fstrings.py
>>> 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.

tuple_examples.py
>>> 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
TIPO_04

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.

list_creation.py
>>> []                          # 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

list_methods.py
>>> 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

list_operations.py
>>> 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

sorting_power.py
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)]
El algoritmo de ordenamiento de Python se llama Timsort (creado por Tim Peters). Es una mezcla de merge sort e insertion sort, y es un ordenamiento estable: elementos iguales mantienen su orden original.
TIPO_05

Tipos de Conjuntos

Python proporciona dos tipos de conjuntos: set (mutable) y frozenset (inmutable). Son colecciones desordenadas de objetos inmutables hashables.

set_operations.py
>>> 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}
Operaciones de Conjuntos
A | B
A & B
A - B
TIPO_06

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).

dict_creation.py
# 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

dict_operations.py
>>> 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

dict_methods.py
>>> 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'}
La función 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.
TIPO_07

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

namedtuple_example.py
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

defaultdict_example.py
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

chainmap_example.py
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'
TIPO_08

Enumeraciones

Las enumeraciones son conjuntos de nombres simbólicos vinculados a valores únicos y constantes. Introducidas en Python 3.4.

enum_example.py
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>
TIPO_09

Consideraciones Finales

Caché de Valores Pequeños

Python utiliza object interning para optimizar memoria en objetos inmutables pequeños.

interning.py
>>> 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

TUPLE
Colección que no cambiará. Hashable (puede ser key de dict)
LIST
Colección ordenada que necesita crecer/modificarse
DICT
Acceso O(1) por clave única. Lookup rápido
Rendimiento: En listas, operaciones como inserción y membership testing toman O(n). En diccionarios son O(1). Considera esto al elegir tu estructura 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.

Basado en "Learn Python Programming" 4th Edition // Fabrizio Romano & Heinrich Kruger

Capítulo 2: Built-In Data Types