LOCALS(), GLOBALS() Y VARS()

ACANTILADO FÓSIL DE LA CULATA, MIRANDO EN DIRECCIÓN AL MACIZO DE TENO, AL NOROESTE DE TENERIFE, ASOMANDO AL FONDO DE LA IMAGEN. LO QUE HACE MILLONES DE AÑOS ERA MAR, AHORA SON CAMPOS DE CULTIVO REPARTIDOS ENTRE LOS MUNICIPIOS DE LOS SILOS Y BUENAVISTA DEL NORTE, CON EL VOLCÁN VIEJO DE TACO EN LA PARTE INFERIOR DERECHA ELEVÁNDOSE EN SOLITARIO. EN SU CIMA EXISTE UNA BALSA, LA MÁS GRANDE DE TODA LA ISLA, USADA PARA RECOGER EL AGUA DE LLUVIA Y REGAR LAS TIERRAS QUE RODEAN SU BASE.


      Continuando con las funciones integradas de Python (las que nos vienen "de serie", por así decirlo), tenemos las funciones globals(), locals() y vars(), donde las dos primeras, como ya habremos caído en la cuenta si recordamos los capítulos dedicados a las funciones definidas por el usuario, se relacionan con las variables globales y las variables locales respectivamente, según se declaren fuera del cuerpo o  ámbito (scope) de la función definida por el usuario, para el caso de las variables globales o, por el contrario, dentro del cuerpo o ámbito de la función, para el caso de las variables locales. La función vars(), por su parte, transita por otros derroteros.

     

     LOCALS():

      

      Esta función devuelve lo que se denomina una TABLA DE SÍMBOLOS LOCAL, generada y sustentada por el compilador desde las tripas de Python, de acuerdo al estado actual (current state) del programa. En realidad, nada del otro mundo: un simple objeto diccionario de los de toda la vida que Python utiliza para conservar información sobre el programa (insistimos, en el estado actual en que se encuentre cuando llamamos a la función), reconocer si una función definida por el usuario está activa (y, en consecuencia, operativa: capaz de hacer aquéllo para la que la hemos programado) si hacemos uso de la función callable() para comprobarlo (v. callable), etc.
Esta TABLA DE SÍMBOLOS LOCAL muestra como claves (keys) del diccionario a nombres de variables mientras que sus valores (values) será los valores propiamente dicho que le hayamos asignado; nombres de clases, cuyo valor será su ubicación en memoria; nombres de métodos, etc.

      COMO YA NOS HABREMOS DADO CUENTA, ACABAMOS DE CITAR CONCEPTOS PROPIOS DE LA PROGRAMACIÓN ORIENTADA A OBJETOS, LA POO, POR SUS SIGLAS EN ESPAÑOL. CIERTAMENTE, AUNQUE SU ESTRUCTURA, CUANDO VEAMOS LOS EJEMPLOS, NOS SUENE A CHINO, LO IMPORTANTE AHORA ES QUEDARNOS CON EL CONCEPTO, HACERNOS UNA IDEA, Y TOMARLA EN CONSIDERACIÓN CUANDO, EN UN PAR DE CAPÍTULOS MÁS, ENTREMOS DE LLENO CON ESTE NUEVO Y MODERNO PARADIGMA DE PROGRAMACIÓN.

Vamos a verlo en un ejemplo donde llamamos a las funciones locals() y globals() sin haber declarado nada. A pelo. Así nos mostrará los VALORES DE PARTIDA y POR  DEFECTO que toma Python para poder realizar su trabajo antes de que hayamos codificado ni una sola coma.:


Como vemos tanto locals() como globals() y, en su momento, vars() también, no llevan argumento alguno en su zona de parámetros.
Si imprimimos en pantalla (con print()) la función locals() o la función globals() obtendremos un objeto diccionario, la TABLA DE SÍMBOLOS, en este caso, similar, idéntico, para una y otra (TABLA DE SÍMBOLOS LOCAL y TABLA DE SÍMBOLOS GLOBAL): una serie de métodos especiales, a los que podemos reconocer fácilmente por su peculiar ortografía: '__nombremétodo__' que ya veremos lo que son cuando entremos en la Programación Orientada a Objetos, próximamente,  que llevan asignados sendos valores. En el primero de ellos podemos reconocer, no obstante, a '__name__' : '__main__', que ya estudiamos por encima en el capítulo que dedicamos a la función main() (v. main) , y que son necesarios para la INTROSPECCIÓN  de Python (en relación con los VALORES DE PARTIDA que mencionábamos más arriba), y por el que el lenguaje se reconoce a sí mismo y nos permite comenzar a programar, por ejemplo, en este IDLE tan apañado. Además, en ambos casos, tanto para locals() como para globals(), las variables locales y globales son las mismas y por ende el resultado es idéntico en ambos casos.

ARENA NEGRA, ARENA DE VOLCÁN. LA ARENA MÁS COMÚN EN LAS PLAYAS DE TENERIFE.

Sin embargo, en el momento de definir una función, la cosa cambia: la función locals() mostrará sólo una TABLA DE SÍMBOLOS LOCAL, con el espacio de nombres de las variables insertadas dentro del ámbito de la función como claves (keys) del diccionario, y sus asignaciones respectivas como valores (values). La función mm por su parte, continúa mostrando los elementos  necesarios para la INTROSPECCIÓN de la que hablábamos en el párrafo anterior, más las variables globales y el espacio de nombres de la función que hemos definido junto a su ubicación en la memoria como valor.


En el ejemplo que sigue se muestra la TABLA DE SÍMBOLOS LOCAL para la función colores():


Podemos asignar funciones a variables y convertir esas mismas variables en variables locales dentro de otra función devolviéndonos un resultado coherente:


Dado que tenemos un diccionario en toda regla podemos manipularlo desde dentro de la misma función para que, al invocarla, nos muestre, por ejemplo, el valor asignado a una única clave (key) específica:



Podemos, incluso, solicitar que se nos muestre la salida en un formato específico como, por ejemplo, una lista. Pero desde fuera de la función, su operatividad es prácticamente nula: nos devuelve una información que, en sí misma, no resulta un objeto que podamos manipular objeto None. Cómo máximo, podremos diseñar que se nos muestre esa misma información, tal y como podemos observar en los dos ejemplos que vienen a continuación.






PRACTICANDO CICLISMO EN LAS CAÑADAS DEL TEIDE, A MÁS DE DOS MIL METROS DE ALTURA SOBRE EL ATLÁNTICO. CENTRO DE TENERIFE.

      GLOBALS():

      

      La función globals() despliega un comportamiento similar a la función locals(), sólo que en este caso afecta exclusivamente a las variables globales, aquéllas, recordemos, que se declaran fuera del ámbito de una función definida por el usuario, devolviendo igualmente una TABLA DE SÍMBOLOS GLOBAL, esto es, un objeto diccionario con los consabidos pares claves/valor.


      VARS():



      La función vars() adolece de una restricción importante: sólo funciona cuando se aplica sobre un objeto que, necesariamente, tiene el atributo diccionario, esto es, dispone del método especial __dict__ y esto es precisamente lo que devuelve, igual que las funciones locals() y globals(), un objeto diccionario. Sin embargo, a pesar de lo dicho, vars() no es aplicable sobre un objeto diccionario tal cual. Si lo hiciéramos, lanzaría una excepción de tipo: TypeError: vars() argument must have __dict__ attribute. Veámoslo y convenzámonos:




De hecho, si llamamos a la función sin pasarle ningún argumento, del mismo modo que sucede con locals() y globals(), nos devolverá la ya famosa TABLA DE SÍMBOLOS, del todo similar a la que ya conocemos en las mismas circunstancias.



De acuerdo a la documentación de Python, sólo podemos recurrir a vars(objeto) es decir, con parámetro, cuando el objeto que pasamos como argumento puede ser modificado (escrito o sobrescrito). Y esta cualidad sólo la tienen objetos como módulos e instancias de clase (POO).
Y paremos de contar.
Existen, sin embargo, objetos que cuentan con restricciones en su escritura como una fórmula de seguridad para evitar errores de programación/ejecución en sus atributos __dict__(), tal es el caso de las clases, que generará una excepción de tipo MappingProxyType para evitar que el diccionario se pueda actualizar de manera directa.



Podemos verlo de una manera más elaborada:


La clase mappingproxy no es otra cosa que un objeto de tipo diccionario con la peculiaridad de que no posee el método especial __setattr__ que permite cambiar un atributo y poner otro en su lugar < set, establecer, + attr, de attribute, atributo o propiedad > (esto es a lo que nos referíamos antes con lo de escritura/sobrescritura y la salvaguarda de datos), precisamente para que el intérprete de Python encuentre rápidamente los atributos de clase (la a en el ejemplo de arriba). 
Tranquilos si nos sentimos confusos con todo esto: a parte de que lo veremos con más detalle cuando entremos con la Programación Orientada a Objetos, en realidad, conocer esto nos ayudará a ser mejores programadores, sí, pero en absoluto resulta imprescindible para programar, incluso, para programar muy pero que muy bien.
Vemos cómo los módulos sí que cuentan con el método especial __dict__.


Veamos qué nos dice Python cuando aplicamos la función vars() sobre un objeto diccionario, una lista y una string:




Finalizamos este capítulo con un ejemplo de uso de vars() bastante más amable, al menos, para que nos deje un buen sabor de boca:



ZIFIOS Y DELFINES EN EL MAR ENTRE LAS ISLAS DE TENERIFE Y  LA GOMERA.


No hay comentarios:

Publicar un comentario