Unidad II · Tema 2.1 Disponible

Nombres y objetos

Identificadores, ligaduras y la diferencia entre objeto y valor.

Objetivo de aprendizaje

Al concluir este tema, el estudiante será capaz de:

  1. Distinguir entre nombre, objeto, valor y ligadura, y describir un programa en esos términos.
  2. Predecir el efecto de una asignación, de una mutación y de una reasignación cuando varios nombres comparten un objeto (alias).
  3. Diferenciar la igualdad (==) de la identidad (is) y reconocer qué tipos son mutables y cuáles inmutables.
  4. Clasificar el momento en que se establece una ligadura: diseño del lenguaje, compilación, enlace o carga, y ejecución.
  5. Comparar el significado de una variable en Python, Java y C++ (referencia a un objeto o contenedor de un valor).

Ruta de trabajo del tema

Etapa Contenido Producto del estudiante
1 Planteamiento inicial Hipótesis escrita
2 Nombres, objetos y ligaduras Vocabulario preciso
3 Alias: dos nombres, un objeto Predicciones verificadas con la corrida
4 Mutar y reasignar; mutables e inmutables Regla de decisión propia
5 Igualdad frente a identidad; copias Distinción aplicada a programas
6 Python, Java y C++ frente a frente Clasificación de fragmentos
7 El momento de la ligadura Clasificación por momento
8 Verificación y reformulación Cuestionario y respuesta revisada

1. Planteamiento inicial

En los lenguajes que se estudian en este curso, un programa manipula datos mediante nombres: a, total, lista. Se acostumbra decir que «una variable guarda un valor», y en muchos casos la frase basta. Sin embargo, existen programas muy cortos cuyo resultado sorprende a quien conserva esa imagen sin matices.

Considere el siguiente programa en Python:

a = [1, 2, 3]
b = a
b.append(4)
print(a)

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Esta hipótesis se retomará al final de la sección 5.


2. Nombres, objetos y ligaduras

Para describir con precisión lo que hace un programa, se necesitan cuatro conceptos.

Definición — Nombre (identificador): cadena de caracteres que se utiliza en el texto del programa para referirse a una entidad: una variable, una función, un tipo o un módulo.

Definición — Objeto: entidad que existe en la memoria durante la ejecución, con una identidad (es distinguible de cualquier otra), un tipo y un valor (su contenido).

Definición — Ligadura (binding): asociación entre un atributo y una entidad. La más frecuente es la que asocia un nombre con un objeto. Otras ligaduras asocian un nombre con un tipo, una dirección de memoria o un alcance.

Un nombre no es un objeto: es una etiqueta que apunta a uno. Un mismo objeto puede tener varios nombres, y un nombre puede apuntar sucesivamente a objetos distintos.

Concepto Dónde se encuentra Ejemplo
Nombre En el texto del programa precio
Objeto En la memoria, durante la ejecución El número 25, con su identidad y su tipo
Ligadura En el entorno (la tabla de nombres vigente) precio → 25

Caso de estudio. En x = 5 ocurren tres cosas: se obtiene el objeto entero 5, se crea (o se reutiliza) el nombre x y se liga el nombre al objeto. Si después se ejecuta x = x + 1, no se modifica el objeto 5: se evalúa x + 1, que produce otro objeto (6), y el nombre x se religa a él. El objeto 5 no cambió, porque los enteros son inmutables.

Importante: en Python no se «declara» el tipo de una variable. El tipo pertenece al objeto, no al nombre: el mismo nombre puede ligarse sucesivamente a un entero, a un texto y a una lista.


3. Alias: dos nombres, un objeto

Definición — Alias: situación en la que dos o más nombres están ligados al mismo objeto. Cualquier modificación del objeto realizada por medio de un nombre es observable por medio de los demás.

Caso de estudio. En el programa de la sección 1, la sentencia b = a no copia la lista: liga el nombre b al objeto al que ya estaba ligado a. Existe una sola lista con dos nombres. Por eso b.append(4) altera el objeto y print(a) muestra el cambio.

Aplicación práctica. La corrida de escritorio siguiente muestra, a la izquierda, el código y, a la derecha, los nombres (en el marco global) y los objetos. Cada objeto tiene una etiqueta de la forma @n que permite comprobar si dos nombres apuntan al mismo. Active el modo de predicción y anticipe cada resultado antes de verlo.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Nota: el botón «Ejecutar» reinicia la corrida. Con «Predecir la salida» marcada, el sistema solicita su hipótesis antes de mostrar los pasos; con «Predecir cada asignación», solicita el valor de cada nombre antes de avanzar.


4. Mutar y reasignar; objetos mutables e inmutables

Sobre un objeto compartido pueden realizarse dos operaciones muy distintas.

Operación Qué ocurre Efecto sobre los demás nombres
Mutación (b.append(4), b[0] = 9) Se modifica el contenido del objeto en su lugar Todos los nombres ligados a él observan el cambio
Reasignación (b = [9]) El nombre b se liga a otro objeto Los demás nombres no se ven afectados

Definición — Objeto mutable e inmutable: un objeto es mutable si su contenido puede cambiar después de creado (las listas y los diccionarios); es inmutable si no puede cambiar (los enteros, los decimales, los textos y las tuplas). Una operación que parece «modificar» un objeto inmutable en realidad crea uno nuevo.

Caso de estudio. Con x = 5, y = x, y = y + 1, tanto x como y estuvieron ligados al mismo objeto 5. Pero el entero es inmutable: y + 1 produjo un objeto distinto y solo y se religó. Al final, x vale 5 y y vale 6. El alias existió, pero no fue observable, porque no hay forma de mutar un entero.

La consecuencia práctica es una regla de decisión: el alias solo importa cuando el objeto es mutable.

Importante — una trampa conocida: con listas, el operador += muta el objeto (equivale a extend), mientras que b = b + [3] crea una lista nueva. Dos expresiones que parecen equivalentes se comportan de manera distinta cuando hay alias. La corrida «La suma de listas, dos formas» permite comprobarlo.

Aplicación práctica. Ejecute los programas siguientes. Antes de cada uno, formule una predicción.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


5. Igualdad, identidad y copias

Definición — Igualdad e identidad: dos objetos son iguales (==) si tienen el mismo contenido; son idénticos (is) si son el mismo objeto. La identidad implica la igualdad, pero no al revés: dos listas distintas con los mismos elementos son iguales y no idénticas.

Esta distinción explica el comportamiento de las copias. Una copia produce un objeto nuevo; el problema es qué ocurre con los objetos contenidos en él.

Definición — Copia superficial y copia profunda: una copia superficial crea un contenedor nuevo, pero sus elementos siguen siendo los mismos objetos que en el original. Una copia profunda copia también, de manera recursiva, los objetos contenidos.

Caso de estudio. Si a = [[1, 2], [3]] y b = a[:], entonces b es una lista nueva (a is b es falso), pero b[0] y a[0] son la misma sublista. Añadir un elemento a b no afecta a a; mutar b[0] sí lo hace.

Importante: la identidad de los enteros pequeños y de ciertos textos puede depender de la implementación (CPython reutiliza los enteros de −5 a 256). Por ello, is se reserva para comparar con None o para razonar sobre alias; no debe usarse para comparar valores.

Aplicación práctica.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Contraste con el planteamiento inicial

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


6. Python, Java y C++ frente a frente

El significado de «variable» no es el mismo en todos los lenguajes. Dos modelos básicos:

Modelo La variable es… Asignar b = a… Lenguajes
Referencia a un objeto Un nombre que apunta a un objeto Copia la referencia: ambos nombres apuntan al mismo objeto Python; Java (para los objetos)
Contenedor de un valor Una zona de memoria que contiene el valor Copia el valor completo en otra zona C y C++ (para los tipos de valor); Java (para los tipos primitivos)

En C++ se puede obtener el primer comportamiento de manera explícita con una referencia (int& b = a;) o con un apuntador.

Aplicación práctica. En cada fragmento se modifica b y se muestra algo de a. Determine si el cambio es visible. La respuesta depende del lenguaje y del tipo del objeto.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.

Nota: en Java, String es inmutable y StringBuilder es mutable; en Python, str es inmutable. La mutabilidad es una propiedad del tipo, no del lenguaje en general.


7. El momento de la ligadura

Definición — Momento de la ligadura (binding time): instante del ciclo de vida de un programa en que se establece una ligadura. Los momentos habituales son el diseño del lenguaje, la compilación, el enlace o la carga y la ejecución.

Caso de estudio. En int contador; (C), el tipo de contador se liga en compilación: el compilador lo conoce y puede detectar usos incorrectos antes de ejecutar. En Python, el tipo del objeto al que apunta x solo se conoce en ejecución. El valor de la variable se liga en ejecución en ambos lenguajes.

La regla general: cuanto antes se establece una ligadura, mayor es la eficiencia y la capacidad de detectar errores; cuanto más tarde, mayor es la flexibilidad. Es el mismo compromiso que se estudió en la pragmática (tema 1.2.3).

Aplicación práctica.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


8. Errores conceptuales frecuentes

Error común: pensar que b = a copia el contenido. En Python y en el caso de los objetos de Java copia la referencia.

Error común: creer que una variable «contiene» una lista. Contiene (mejor dicho, nombra) una referencia a la lista; la lista existe independientemente.

Error común: pensar que y = y + 1 modifica el entero. Los enteros son inmutables: se crea un objeto nuevo.

Error común: usar is para comparar valores. Para el contenido se usa ==; is se reserva para identidad y para comparar con None.

Error común: creer que una copia superficial aísla por completo el original. Los objetos contenidos siguen compartidos.


9. Verificación del tema

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


10. Libreta de trabajo

Reúna sus respuestas, sus predicciones y los resultados de las prácticas; revíselos y expórtelos como evidencia para el portafolio.

Este laboratorio interactivo requiere JavaScript habilitado en el navegador.


11. Preguntas de reflexión

  1. Describa con los términos nombre, objeto y ligadura qué ocurre cuando una función recibe una lista y la modifica. ¿Qué consecuencias tiene para quien la llama?
  2. ¿Qué ventajas tiene que los textos (str) sean inmutables? ¿Qué costo tiene al construir un texto largo concatenando muchas veces?
  3. ¿Por qué C++ ofrece tanto copia como referencia, y Python solo la referencia? Relacione su respuesta con los criterios de la pragmática.
  4. Proponga un fragmento de programa en el que un alias no deseado provoque un error difícil de encontrar. ¿Cómo lo evitaría?
  5. ¿Qué información adicional necesitaría para saber, en cualquier lenguaje, si una asignación copia o comparte?

12. Lecturas recomendadas

  • Sebesta, R. (2015). Concepts of programming languages (11th ed.), capítulo sobre nombres, ligaduras y alcance (sección sobre ligaduras y momentos de ligadura). Pearson.
  • Python Software Foundation. The Python Language Reference, sección «Data model» (objetos, valores y tipos). Acceso libre en docs.python.org.
  • Scott, M. (2015). Programming language pragmatics (4th ed.), capítulo sobre nombres, alcances y ligaduras. Morgan Kaufmann.