Search code examples
pythonclassglobalnameerror

NameError: name 'rank' is not defined even though i have mentioned it in global


The code below is a simplified version of a bigger code. The main action i want to perform is to use and change rank and progress inside the inc_progress(self) function.

class User:
    rank=-8
    progress=0
    def inc_progress(self):
        global rank, progress
        rank+=1
        print(rank,progress)



u=User()
u.inc_progress()

but it gives me the error: NameError: name 'rank' is not defined. Did you mean: 'range'?

does anyone know a possible fix for this issue, so that I can use and change the values of rank and progress in the inc_progress(self) function


Solution

  • By defining rank and progress outside of __init__, you've defined them as class variables, meaning that they belong to the class and will be available to all instances of that class. https://pynative.com/python-class-variables/

    Here's a modified version of your code that does what you're expecting (and probably some things that you aren't!)

    class User:
    rank=-8
    progress=0
    def inc_progress(self):
        User.rank+=1
        print(User.rank, User.progress)
    
    u=User()
    u.inc_progress() # Output: -7, 0
    

    Ok great! Problem solved, right? Well, maybe. Look at this.

    u=User()
    u.inc_progress() # Output: -7, 0
    u2 = User()
    print(u2.rank, u2.progress) # Output: -7, 0
    

    Wait, what? That newly created instance of User has rank=-7 instead of -8! That's class variables for you. If you want rank and progress to be specific to the instance, then define them during initialization and access them as usual with self

    class User:
    def __init__(self):
        self.rank=-8
        self.progress=0
    def inc_progress(self):
        self.rank+=1
        print(self.rank, self.progress)
    
    u=User()
    u.inc_progress() # Output: -7, 0
    u2 = User()
    print(u2.rank, u2.progress) # Output: -8, 0