Home > Back-end >  global variable not working properly inside class
global variable not working properly inside class

Time:07-21

The Python code inside the 'outer' function works fine by itself, but for some reason when it's placed inside a class, things stop working and I don't understand why.

(And I realize I could just pass data as a variable inside the function or declare data in the outer scope, but this is a pet example which represents other code where I'd rather not do this. And anyway, I'd like to know why this doesn't work)

How can I, within 'inner', (1) check the value of data, and then (2) change its value? (with data declared within 'outer')

class Obj:
    def __init__(self): 
        pass

    def outer(self):
        data = 1
        def inner():
            global data
            if data: pass      # without this line, file runs
            data = 2
        inner()
        
o = Obj()
o.outer()

CodePudding user response:

@IainShelvington had a correct solution: I needed to use the nonlocal keyword instead of global. Just replacing those two words resolved the error and made things work as expected.

CodePudding user response:

I am not sure what you are trying to achieve here.

TLDR: If you want to keep using a global vaiable, which all class shared the same value. This maybe what you want

class Obj:
    def __init__(self): 
        pass

    def outer(self):
        global data
        data = 1
        def inner():
            global data
            if data: pass     
            data = 2
        inner()
        
o = Obj()
o.outer()
print(data) # output: 2

if you are trying to use a local variable, each class have a seperate value. This may be what you want:

class Obj:
    def __init__(self): 
        pass

    def outer(self):
        data = 1
        def inner():
            nonlocal data
            if data: pass
            data = 2
        inner()
        print(data)
        
o = Obj()
o.outer() # output: 2

which I would prefer to do in another way just to be more clear...

class Obj:
    def __init__(self): 
        pass

    def outer(self):
        data = 1
        def inner(input):
            if input: pass
            return 2
        data = inner(data)
        print(data)
        
o = Obj()
o.outer() # output: 2

A Longer Explaination on global:

Python program look find a variable in local scope, outer scope and eventually global scope normally. If you use global, you are telling the function to skip inner scope and outer scope and jump straight to global scope.

In your scenario, global IS WORKING AS INTENDED as it jumped to global scope in inner(), while data is in outer scope, that's why they didn't match together. In this case, you have different options.

  1. Use a global variable which all instance shared(Not Recommanded)
  2. Use a class variable which all instance shared
  3. Use nonlocal to let inner search data from outer scope(Not Recommanded)
  4. Use a instance variable which each instance have it's own value.

Now 1 and 3 is not recommended as I stated. This is because changing the default scope of your variable may result in unexpected change in variable values and hence create difficulties in debugging. Class variable and Instance variable are create solely for this purpose and you should use them instead.

  • Related