Python: Hace falta valor

Objetivo: entender cómo responde Python ante la modificación in situ de un objeto.

Hace unos días te presenté un fenómeno cuya comprensión era esencial para entender el modelo de memoria de Python basado en referencias. Quiero mostrarte hoy otro directamente relacionado con él.

Voy a proponerte un problema que te ayudará a testear tu conocimiento sobre Python…

Partamos de alguna operación que modifique in situ el valor de un objeto. Sin ir más lejos, tomemos, por ejemplo, el recientemente aprendido método reverse() para invertir una lista:

>>> a = [1, 2, 3]
>>> b = a.reverse()

Mi pregunta es la siguiente: ¿qué valor crees que tiene la variable b?

Recuerda que el método reverse() invierte la lista in situ (para hacerlo creando un objeto diferente recurríamos al slicing).

¿Crees que b tendrá por valor [3, 2, 1]? Se realiza la inversión y acto seguido b toma ese valor, de modo que a b le corresponde un valor de [3, 2, 1] también, como a.

O, por el contrario, ¿valdrá b, a pesar de todo [1, 2, 3]?

¿Qué piensas?

¿Sabes ya la respuesta sin comprobarla en el intérprete interactivo?

¿Por qué crees que sucede así?

¿Pondrías tu mano en el fuego?

Lamento decirte que, tanto si has elegido la primera opción como si has optado por la segunda te has equivocado completamente.

Veamos la respuesta al problema mostrando el valor de ambas variables tras la operación:

>>> a = [1, 2, 3]
>>> b = a.reverse()
>>> 
>>> a
[3, 2, 1]
>>> b
>>> 

Sorpresa: la variable b no tiene ningún valor, lo que equivale a decir que es None.

>>> type(b)
<class 'NoneType'>

Este fenómemo lo has tenido siempre delante de tus narices, aunque con mucha probabilidad te haya pasado desapercibido.

Por ejemplo, observa cómo responde el intérprete interactivo después de cualquier operación que implique la creación de un nuevo objeto:

>>> 2+3
5
>>> 'pradera'[0:3]
'pra'
>>> [1, 2, 3][::-1]
[3, 2, 1]
>>> 

Es decir, devuelve el resultado de esa operación. Si hubiésemos asignado una variable a esa operación, su valor sería precisamente ese.

Pero presta mucho atención qué sucede ante operaciones in situ, que actúan sobre el propio objeto:

>>> [1, 2, 3].append(4)
>>> [1, 2, 4].reverse()
>>> 

¡Python no devuelve absolutamente nada! O, lo que es lo mismo, devuelve el valor None.

No se trata de ningún bug de Python, sino una consideración de diseño refinadísima.

Python está diseñado expresamente así, de modo que, explícitamente, cada vez que una operación de cualquier tipo modifique in situ un objeto, no se devolverá ningún valor.

Por eso la variable b, en nuestro problema, no toma ningún valor. La inversión de la lista, desde luego, ha hecho su efecto en a, pero no hay valor devuelto por esta inversión.

Hace falta valor para tomar una decisión así, pero es algo absolutamente coherente con el modelo de memoria de Python. De no hacerlo, el sistema entero cojearía en operaciones encadenadas que combinasen modificaciones in situ con creaciones de nuevos objetos: sólo podemos encadenar operaciones (por ejemplo, ejecutando un método que actúe sobre el resultado de otro) cuando esas operaciones impliquen la creación de nuevos objetos. Si en cualquiera de ellas hay una modificación in situ no habrá valor devuelto.

En nuestro pequeño problema, la forma correcta de proceder sería esta:

>>> a = [1, 2, 3]
>>> a.reverse()
>>> b = a
>>> a
[3, 2, 1]
>>> b
[3, 2, 1]

Es decir, invertimos la lista a y sólo después realizamos la asignación de b, una vez a ha sufrido su mutación in situ.

Un pequeño precio a pagar que asegura coherencia y claridad en el código.

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/10/python-hace-falta-valor/


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Consulta el índice completo de artículos relacionados con Python.

Deja un comentario

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies