Python Global Variables - Not Defined?

20,103

Solution 1

You have to use global df inside the function that needs to modify the global variable. Otherwise (if writing to it), you are creating a local scoped variable of the same name inside the function and your changes won't be reflected in the global one.

p = "bla"

def func():
    print("print from func:", p)      # works, readonly access, prints global one

def func1():
    try: 
        print("print from func:", p)  # error, python does not know you mean the global one
        p = 22                        # because function overrides global with local name   
    except UnboundLocalError as unb:
        print(unb)
        
def func2():
    global p
    p = "blubb"                       # modifies the global p

print(p)
func()
func1()
print(p)
func2()
print(p)

Output:

bla   # global

print from func: bla    # readonly global

local variable 'p' referenced before assignment  # same named local var confusion

bla    # global
blubb  # changed global

Solution 2

You have to use the global keyword inside the function rather than outside. All the df that you have defined inside your function are locally scoped. Here is the right way -

df = pd.DataFrame() # No need to use global here

def __init__(self, master):
    global df # declare here
    df = None
....

def load(self):
    global df # declare here
    ....
    df = pd.read_csv(filepath)

def save(self):
    global df # declare here
    ....
    df = df.append(...)

Solution 3

for anyone coming here using python3 - try using nonlocal instead of global - a new construct introduced in python3 which allows you to mutate and read global variables in local scope

Share:
20,103
Axioms
Author by

Axioms

Updated on December 28, 2021

Comments

  • Axioms
    Axioms over 2 years

    I'm running into an issue where a global variable isn't "remembered" after it's modified in 2 different functions. The variable df is supposed to be a data frame, and it doesn't point to anything until the user loads in the right file. This is similar to something I have (using pandas and tkinter):

    global df
    
    class World:
    
        def __init__(self, master):
            df = None
            ....
    
        def load(self):
            ....
            df = pd.read_csv(filepath)
    
        def save(self):
            ....
            df = df.append(...)
    

    save() is always called after load(). Thing is, when I call save(), I get the error that "df is not defined." I thought df got its initial assignment in init(), and then got "updated" in load()? What am I doing wrong here?

  • Axioms
    Axioms about 6 years
    Oh, so do I need to declare it every time I need to call it? There isn't a way for it to be "universally" remembered inside a class?
  • Osman Mesut Ozcan
    Osman Mesut Ozcan about 6 years
    @Axioms if you want it to be available for all functions in a class you can make it a class variable. Other than that nothing much to do but to write it in every function needed
  • Patrick Artner
    Patrick Artner about 6 years
    @Axioms I prefer to not use globals at all - I mostly provide them as parameters to functions or put them as member variables inside classes.
  • Axioms
    Axioms about 6 years
    So if I set x = "hello" right after I declare a class (i.e. class variable), then would that x be "hello" in every function of that class?
  • Patrick Artner
    Patrick Artner about 6 years
    @Axioms That would be a "static" Class-Variable, its shared between instances of that class, one changes it - all gets the change. Unless you need to create 20 different worlds, accessing the same df I would probably use a self.df = None inside the __init__(self, ... ), load it inside load self.df = pd.read_csv(...) etc.
  • Axioms
    Axioms about 6 years
    Ah, guess I was confusing global variables with class variables. Got it, thank you.