Variables en Python: etiquetas, no cajas

Cuando vienes de C, Java o casi cualquier otro lenguaje, traes una imagen mental muy concreta de lo que es una variable: una cajita en memoria que contiene un valor. En Python esa imagen te va a traicionar. Aquí una variable es una etiqueta —o si prefieres, un nombre— que apunta a un objeto que vive en otro lado.

La distinción no es filosófica. Cambia cómo se comporta tu código de maneras muy concretas, y todo lo que viene después —mutabilidad, referencias compartidas, paso de argumentos— solo tiene sentido si tienes bien puesta esta metáfora.

Cómo funciona realmente la asignación

Cuando escribes a = 42, Python hace dos cosas separadas:

  1. Crea el objeto 42 en memoria (un objeto de tipo int con el valor 42).
  2. Adhiere la etiqueta a a ese objeto.

a no es el 42 ni lo contiene. a es un nombre que referencia ese objeto. La diferencia se hace visible en cuanto haces una segunda asignación:

a = 42
a = "hola"

El objeto 42 sigue existiendo en memoria (por un momento, al menos). Solo moviste la etiqueta. No destruiste nada activamente —el recolector de basura de Python se encargará del 42 cuando compruebe que ya nadie lo referencia.

La función id() devuelve un número entero que identifica de forma única a un objeto durante su tiempo de vida. En CPython eso es la dirección de memoria, lo que hace que sea la herramienta perfecta para ver exactamente esto en acción.

# Ejemplo completo y ejecutable

a = 42
print(id(a))   # identidad del objeto 42

a = "hola"
print(id(a))   # identidad de un objeto distinto — el número cambió

# Dos etiquetas, un solo objeto
b = a
print(id(a) == id(b))   # True: ambas etiquetas apuntan al mismo objeto

# Asignación independiente con el mismo valor
x = 1000
y = 1000
# CPython puede (o no) reutilizar el objeto; con enteros pequeños lo hace siempre
# Con enteros grandes el resultado puede sorprenderte:
print(id(x) == id(y))   # probablemente False fuera del REPL

# La etiqueta puede viajar a cualquier tipo de objeto
c = 3.14
print(type(c), id(c))

c = [1, 2, 3]
print(type(c), id(c))   # id diferente, tipo diferente — misma etiqueta 'c'

Lo que el código realmente te está mostrando

Fíjate en el bloque b = a. No hay copia de ningún dato. Python toma la misma referencia que tiene a y crea una segunda etiqueta b que apunta al mismo objeto. Puedes comprobarlo porque id(a) == id(b) da True. Aquí es donde la metáfora de “la caja” explota: si a fuera una caja y hicieras b = a, esperarías dos cajas con el mismo contenido. En cambio tienes dos nombres para el mismo objeto.

Esto tiene una consecuencia directa con objetos mutables (listas, diccionarios, clases propias): si modificas el objeto a través de una etiqueta, lo ves modificado a través de la otra, porque es el mismo objeto. Con objetos inmutables (enteros, strings, tuplas) no pasa nada visible porque no puedes modificarlos en el lugar —solo puedes reasignar la etiqueta a un objeto nuevo.

El caso de x = 1000 / y = 1000 ilustra algo más sutil: Python no garantiza que dos asignaciones con el mismo valor literal apunten al mismo objeto, salvo para ciertos enteros pequeños (−5 a 256, por convenio de implementación en CPython) y strings cortos sin espacios. No programes asumiendo que id(x) == id(y) será True; eso es un detalle de implementación, no parte del lenguaje.

Por último, fíjate en que c cambia de float a list sin ningún problema. Python no asocia el tipo al nombre, sino al objeto. La etiqueta c es solo un nombre; el objeto que referencia sí tiene tipo.

Errores que debes conocer

Error: asumir que b = a crea una copia independiente cuando a apunta a una lista, y luego sorprenderte cuando modificar b modifica también a.

# ❌ Incorrecto — mismo objeto, dos etiquetas
a = [1, 2, 3]
b = a
b.append(4)
print(a)   # [1, 2, 3, 4] — ¿no esperabas esto?

# ✅ Correcto — copia superficial del objeto lista
a = [1, 2, 3]
b = a.copy()   # o list(a), o a[:]
b.append(4)
print(a)   # [1, 2, 3] — ahora sí son independientes

.copy() crea un objeto lista nuevo con los mismos elementos, así que b obtiene su propia identidad y modificarla no afecta a a.

Error: comparar identidad con == cuando lo que quieres saber es si dos variables apuntan al mismo objeto.

# ❌ Confunde igualdad de valor con identidad
x = [1, 2]
y = [1, 2]
print(x == y)    # True — mismo valor
print(x is y)    # False — objetos distintos

# ✅ Usa 'is' cuando la identidad importa (p. ej., comparar con None)
result = None
if result is None:   # correcto
    print("sin resultado")

== llama al método __eq__ del objeto y compara valores; is compara identidades numéricas (id(x) == id(y)). Usa is solo para None, True, False y casos donde la identidad del objeto importa explícitamente.

29

Dejar un comentario

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

Scroll al inicio