Diferencia entre variables en Python y otros lenguajes



La forma en la que Python maneja los objetos (evito el nombre variables, ya verás por qué) es un tanto diferente a lo que generalmente se está acostumbrado por otros lenguajes, y puede prestar a la confusión para quienes lo ignoren. Este artículo es una traducción con algunas ligeras modificaciones de una sección del texto Code Like a Pythonista: Idiomatic Python y se encuentra bajo los términos de la licencia Creative Commons Attribution/Share-Alike (BY-SA).

En muchos otros lenguajes, como C o Visual Basic, por poner algunos ejemplos, asignar a una variable es similar a poner un valor en una caja.

int a = 1;

La caja a ahora contiene el número entero 1.

Asignar otro valor a la misma variable reemplaza el contenido de la caja:

a = 2;

Ahora la caja a contiene el entero 2. Entonces, el código anterior se leería “poner el valor 2 en el contenedor a“.

Asignar una variable a otra hace una copia del valor que contiene la primera y lo pone en la nueva caja.

int b = a;

b es una segunda caja, con una copia del número 2. La caja a tiene una copia separada. Por ende la expresión indicaría “poner el valor que contiene a en b, sin alterar a.”

a no es b; son dos contenedores diferentes simplemente con el mismo número.

Python, en cambio, tiene “nombres”. Un “nombre” o “identificador” es como una etiqueta atada a un objeto (en este caso un número entero).

a = 1

Aquí, el número entero 1 (que, como todas las cosas en Python, es un objeto) tiene una etiqueta llamada a.

Si reasignamos al identificador a, simplemente movemos la etiqueta a otro objeto.

a = 2

Ahora el nombre a está atado al objeto 2 (que también es un número entero).

El objeto original (el número 1) ya no tiene la etiqueta a. Puede que todavía exista, pero no podemos acceder a él a través de esta etiqueta. (Cuando un objeto no tiene más referencias o etiquetas, es eliminado).

Si asignamos un nombre (o identificador) a otro, solo estamos atanado otra etiqueta a un objeto existente.

b = a

El nombre b es simplemente una segunda etiqueta atada al mismo objeto que a.

Si bien comunmente nos referimos a “variables” incluso en Python (porque es una terminología convencional), en realidad queremos decir “nombres” o “identificadores”. En Python, las “variables” no son cajas que contienen valores sino etiquetas asociadas a un valor (objeto) determinado.

Antes de finalizar, veamos un ejemplo. El operador is en Python permite determinar si dos nombres o identificadores hacen referencia al mismo objeto.

>>> a = []
>>> b = a
>>> a is b
True

En esta secuencia tenemos dos identificadores (a y b) pero solo un objeto (la lista). Por ende, podemos utilizarlos indistintamente para añadir elementos a la lista.

>>> a.append(1)
>>> b.append(2)
>>> a
[1, 2]
>>> b
[1, 2]

Observemos ahora el contraejemplo.

>>> a = []
>>> b = []
>>> a is b
False

Aquí hay dos identificadores y dos objetos. a y b contienen dos listas diferentes, aunque equivalentes.

>>> a == b
True

En tanto alguna de ellas no sea modificada…

>>> b.append(1)
>>> a == b
False

Un error en el que incurren muchos programadores de Python es al momento de asignar objetos mutables (como una lista) como argumentos por defecto.

def mala_funcion(nuevo_item, una_lista=[]):
    una_lista.append(nuevo_item)
    return una_lista

El problema aquí es que el valor por defecto de una_lista, una lista vacía, es evaluado en el momento en el que se define la función. Entonces, cada vez que llamas a la función, obtienes el mismo valor por defecto. Pruébalo varias veces:

>>> print(mala_funcion("uno"))
['uno']
>>> print(mala_funcion("dos"))
['uno', 'dos']

Las listas son objetos mutables; puedes cambiar su contenido. La forma correcta de obtener una lista por defecto (o un diccionaro, o un set) es crearla durante la ejecución, dentro de la función:

def buena_funcion(nuevo_item, una_lista=None):
    if una_lista is None:
        una_lista = []
    una_lista.append(nuevo_item)
    return una_lista

Ahora el resultado es el esperado:

>>> print(buena_funcion("uno"))
['uno']
>>> print(buena_funcion("dos"))
['dos']



Deja un comentario