'Global variable not being referenced for inner scope declaration in Python

Python is declaring a variable that is already in the global scope. The code below creates an exception: "local variable 'OLDTOTALNUMPASSED' referenced before assignment"

#THIS CREATES AN EXCEPTION
class Main():
    global OLDTOTALNUMPASSED
    global OLDTOTALNUMFAILED
    global OLDRUNNINGCONSECUTIVEFAILURES
    OLDTOTALNUMPASSED = 0
    OLDTOTALNUMFAILED = 0
    OLDRUNNINGCONSECUTIVEFAILURES = 0

    def foo_bar():
        if(not(OLDTOTALNUMPASSED == 0 and OLDTOTALNUMFAILED == 0 and OLDRUNNINGCONSECUTIVEFAILURES == 0)):
            **OLDTOTALNUMPASSED** = myHMI.total_num_passed
            **OLDTOTALNUMFAILED** = myHMI.total_num_failed
            **OLDRUNNINGCONSECUTIVEFAILURES** = myHMI.running_consecutive_failures

But if I take the references out of the conditional body, it passes. Obviously python looks ahead and declares a new variable even though there is already a global variable.

#THIS PASSES
class Main():
    global OLDTOTALNUMPASSED
    global OLDTOTALNUMFAILED
    global OLDRUNNINGCONSECUTIVEFAILURES
    OLDTOTALNUMPASSED = 0
    OLDTOTALNUMFAILED = 0
    OLDRUNNINGCONSECUTIVEFAILURES = 0

    def foo_bar():
        if(not(OLDTOTALNUMPASSED == 0 and OLDTOTALNUMFAILED == 0 and OLDRUNNINGCONSECUTIVEFAILURES == 0)):
            **a** = myHMI.total_num_passed
            **b** = myHMI.total_num_failed
            **c** = myHMI.running_consecutive_failures

I have three questions:

A: Is it Python or is it the Interpreter that looks ahead into the conditional body before the conditional statement.

B: Why does Python declare a new variable when that variable is already in the global scope

C: How do I get python to refer to the global variable. I can't use self. because



Solution 1:[1]

Turns out, the variable Needs to be global in both the foo_bar() as well as the class. If it is not global in either the class or the function it does not work.

#THIS PASSES
class Main():
global OLDTOTALNUMPASSED
global OLDTOTALNUMFAILED
global OLDRUNNINGCONSECUTIVEFAILURES
OLDTOTALNUMPASSED = 0
OLDTOTALNUMFAILED = 0
OLDRUNNINGCONSECUTIVEFAILURES = 0

def foo_bar():
    global OLDTOTALNUMPASSEDLNUMPASSED
    global OLDTOTALNUMPASSEDLNUMFAILED
    global OLDRUNNINGCONSECUTIVEFAILURES
    if(not(OLDTOTALNUMPASSED == 0 and OLDTOTALNUMFAILED == 0 and OLDRUNNINGCONSECUTIVEFAILURES == 0)):
        OLDTOTALNUMPASSED = myHMI.total_num_passed
        OLDTOTALNUMFAILED = myHMI.total_num_failed
        OLDRUNNINGCONSECUTIVEFAILURES = myHMI.running_consecutive_failures

Solution 2:[2]

Actually, the best answer to this problem may be to use self. You can pass the class itself as a parameter to the function and call self.variable

#THIS PASSES
class Main():
OLDTOTALNUMPASSED = 0
OLDTOTALNUMFAILED = 0
OLDRUNNINGCONSECUTIVEFAILURES = 0

def foo_bar(self):
    if(not(self.OLDTOTALNUMPASSED == 0 and self.OLDTOTALNUMFAILED == 0 and self.OLDRUNNINGCONSECUTIVEFAILURES == 0)):
        self.OLDTOTALNUMPASSED = myHMI.total_num_passed
        self.OLDTOTALNUMFAILED = myHMI.total_num_failed
        self.OLDRUNNINGCONSECUTIVEFAILURES = myHMI.running_consecutive_failures

Main.foo_bar(Main)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Harry Tee
Solution 2 Harry Tee