How to access global variables in python

2

I have been developing this project for some time, I only had it in a single file and when I modularized it I had problems compiling the type "global name 'file' is not defined", where file is a global variable. I have a file "main" which is the following:

#Laberinto.py

#---------------------------IMPORTACION DE LIBRERIAS------------------------------------
from Clases import Jugador 
from Clases import Camino
from Clases import Arbol
from Funciones import cargarArchivo
from Funciones import cargarLaberinto
from Funciones import MazeRunner
#-------------------------FIN IMPORTACION DE LIBRERIAS----------------------    
#---------------------------INICIALIZACION DE VARIABLES GLOBALES----------
arbol = Arbol(60,120)
nodoPadre = arbol.listaNodos [0]
ancho = 0
alto = 0
laberinto = []#matriz de 1's y 0's que definen al laberinto
mapaConocido = []
archivo = open( "file/matriz.txt", "r" )#archivo que contiene la informacion del laberinto
listaMuros = []#lista de todos los muros con su posicion
listaCamino = []
listaVisitados = []
#-------------------------FIN INICIALIZACION DE VARIABLES GLOBALES-----------------------------------

def main(ancho,alto):
    cargarArchivo(archivo,laberinto,mapaConocido)
    alto,ancho = cargarLaberinto(laberinto,listaCamino,listaMuros,ancho,alto)   
    jugador = Jugador(ancho,alto)
    MazeRunner(jugador,listaCamino,listaMuros,listaVisitados,ancho,alto,mapaConocido,arbol,nodoPadre)

main(ancho,alto)

The previous error is passed by passing to each function the global variables that will be used but as some functions send others to call in their procedure, these also pass the variables that will occupy and I get a mess pass as many variables if they are defined in the main file as global (not with the global word but outside any function) and can not modify them from each function without passing them as a parameter. This if the functions did if they were in the same file, but I wanted to make it more modularized. My question is whether there is any way for functions in independent modules to access these global variables without passing them as a parameter or can they only do so while in the same module where the variables were defined?

Here I add the code of another of the modules (loadFile):

#cargarArchivo.py
def cargarArchivo(archivo,laberinto,mapaConocido):#Funcion que lee el archivo txt   con la forma del laberinto
    for line in archivo.readlines():
        fila = list(line)
        fila.pop()

        while fila.count(',') != 0: #busca y retira las comas en la lista
            fila.remove(',')

        print fila      
        laberinto.append( fila )
        mapaConocido.append( fila )
    
asked by Marcos López 11.04.2018 в 08:10
source

3 answers

1

Let's start by making it clear that the abuse of global variables (another topic is the "constants") is in principle a bad practice, dangerous in some cases leading to unexpected side effects, besides making the code unnecessarily less readable and contributing to the known as spaghetti code .

In my opinion, it does not make much sense to use shared global variables between modules just because we want to save ourselves writing the arguments when calling a function, the justification for using a global variable should go further than that. Even going one step further, functions such as cargarArchivo should themselves handle the opening and closing of the file correctly and return the lists, not modify in situ the lists that arrive to them using an open file outside the function, leaving it in the air where and how that file is closed or where the cursor is located at a given moment.

This may seem like it is not very important, but it has a lot. In a moderately large project (and regardless of the bugs that can be caused) using this type of patterns makes someone remember you and not for good when it comes to maintaining that code, even oneself when after a while he reviews his own code He ends up repenting.

Having said that, what you want can be done but taking into account that:

  

The global variables in Python are global with respect to the module in which they are declared, not with respect to the whole process.

This means that if we have:

  • functions.py :

    def foo():
        global cad
        print(cad)
    
  • main.py :

    import funciones
    
    cad = "Hola"
    funciones.foo()
    

We will have an error:

Traceback (most recent call last):
  File "D:\main.py", line 4, in <module>
    funciones.foo()
  File "D:\funciones.py", line 3, in foo
    print(cad)
NameError: name 'cad' is not defined

cad is global in main.py but it is not in functions.py . Can you get funciones.foo access it without passing it as an argument (which I repeat, is normal)? The answer is yes, it is and in different ways. For example:

  • Use módulo.variable to assign (and in this case define) the variable in the same funciones.py from main.py :

    import funciones
    
    cad = "Hola"
    funciones.cad = cad
    funciones.foo()
    

    Very nice, but cad is an immutable object because it is a string, if we happen to modify cad then we can take a surprise:

    >>> cad = "Adios"
    >>> funciones.foo()
    'Hola'
    
  • Use a third module to share the global variables that are imported by all those who share them:

    • global.py :

      cad = "Hola"
      
    • functions.py :

      import globales
      
      def foo():
          print(globales.cad)
      
    • main.py :

      import funciones
      import globales
      
      
      funciones.foo() # 'Hola'
      globales.cad = "Adios"
      funciones.foo() # 'Adios' 
      

The remedy is worse than the disease, we should not tend to make global variables that strictly do not require it (there are cases in which they are necessary and justified its use, especially in the case of constants), the tendency must be the inverse . As the Python zen says:

  

Namespaces are a great idea, you have to do more of that!

A couple of observations:

  • Always use global variable in functions that use a global variable, even if they are mutable objects like the lists in your example.

  • Never use readlines unless you want a list with the lines of the file to be used directly. In other cases it is very inefficient and unnecessary. In your function cargarArchivo is simpler and more efficient to do:

    for line in archivo:
        fila = list(line.rstrip().replace(",", ""))
        print fila 
    

    or if your lines are of the form " a,b,c,d,e " (a single character separated by commas):

    for line in archivo:
        fila = line.rstrip().split(",")
        print fila
    
answered by 11.04.2018 / 12:04
source
0

I'll give you an example:

file: const.py

VAT = 0.21

file: main.py

from const import VAT

price = 40

Final price = price * (1 + VAT)

print (final price)

    
answered by 11.04.2018 в 09:29
0

In python the global variables within a function are read only, if you want to modify them you need to indicate it with the reserved word " global " as in this example:

x = 'Soy global'

def unaFuncion():
    print x

def otraFuncion():
    global x
    x = 'Me han modificado'
    print x

unaFuncion()
otraFuncion()

print x  # La variable "x" en este punto tiene el valor modificado

The previous example will return the following strings:

  

I am global

     

They have modified me

     

They have modified me

As you can see if you only want to obtain its value, you do not need to indicate that you access a global variable, while to modify its value if you have to do so.

    
answered by 11.04.2018 в 09:51