Why Does This Unboundlocalerror Occur (Closure)

Why does this UnboundLocalError occur (closure)?

Python doesn't have variable declarations, so it has to figure out the scope of variables itself. It does so by a simple rule: If there is an assignment to a variable inside a function, that variable is considered local.[1] Thus, the line

counter += 1

implicitly makes counter local to increment(). Trying to execute this line, though, will try to read the value of the local variable counter before it is assigned, resulting in an UnboundLocalError.[2]

If counter is a global variable, the global keyword will help. If increment() is a local function and counter a local variable, you can use nonlocal in Python 3.x.

UnboundLocalError: local variable referenced before assignment in python closure

You have overwritten the variable with filename = os.path.join(os.getcwd(), filename), if you change the filename = to something other than filename you won't get a local variable 'filename' referenced before assignment error.

Once you set filename = you are no longer referring to the parameter filename that is passed in you are referring to the local filename in the scope of the inner function which you try to use in the if before you have it defined.

You will have the same problem with dest, if you change the two lines and the other variables to something like:

filename_ = os.path.join(os.getcwd(), filename)
dest_ = os.path.join(dest, filename)

You will see the code runs fine as filename now refers to the parameter not to a local variable defined in your inner function.

You will see the exact same behaviour if you try to reassign x in your first function and try to access x before you have defined it:

def makeInc(x, y):
def inc():
print y + x # will cause referenced before assignment error
x = 5 # now x is local to the inner func, the x from the outer function is overridden
return y + x
return inc

If you print the __closure__ attribute you will see what happens:

def makeInc(x, y):
def inc():
return y + x
return inc

inc5 = makeInc(5, 10)
inc10 = makeInc(10, 5)
print(inc5.__closure__)
(<cell at 0x7f180df67e50: int object at 0xef00f8>, <cell at 0x7f180df67fa0: int object at 0xef0080>)

Now reassigning x:

def makeInc(x, y):
def inc():
print y + x
x= 5
return y + x
return inc

inc5 = makeInc(5, 10)
inc10 = makeInc(10, 5)
print(inc5.__closure__)
(<cell at 0x7fea11889fd8: int object at 0x291e080>,)

After reassigning in the inner function, there is no longer a reference to x.

So basically the fundamental difference between your two original functions is that in one you are reassigning the variable in the local scope and in the other you are not. As you can see from the code above if you do something similar in the first function the outcome is exactly the same.

There is a nice tut here on scopes LEGB etc..

Why I encounter an UnboundLocalError when I wrote a python closure, but in another similar code snippet I didn't?

The assignment x = temp creates a new local variable that shadows the non-local x defined by wrapper. Even though temp = x + 1 precedes it at run time, it still refers to the local variable x that isn't yet initialized.

UnboundLocalError: local variable 'actionNumber' referenced before assignment and Array

Since you are defining a function, it is treating any reference to actionNumber as a local variable, a variable that exists only within the function with no connection to the global variable actionNumber.

You can add global actionNumber as the first line to your function, which will make any reference to actionNumber in the function, a reference to the global actionNumber, not a local one. However, I suggest you define actionNumber as 0 in the function unless you need to use actionNumber in multiple difference functions/outside the function.

So, you're fixed code would be either:

actionNumber = 0

dataX = []
dataY = []

f = open("track_cursor_position_log.txt", "r")
#print(f.read())


def mainLoop():
#I need to store the first line of the file into dataX, then the second into dataY, then the 3rd into dataX, and so on...
global actionNumber

actionNumber = actionNumber + 1

mainLoop()

mainLoop()

or

dataX = []
dataY = []

f = open("track_cursor_position_log.txt", "r")
#print(f.read())


def mainLoop():
#I need to store the first line of the file into dataX, then the second into dataY, then the 3rd into dataX, and so on...
actionNumber = 0

actionNumber = actionNumber + 1

mainLoop()

mainLoop()

Also, as an aside, actionNumber += 1 would be the same as actionNumber = actionNumber + 1

UnboundLocalError on local variable when reassigned after first use

Python treats variables in functions differently depending on whether you assign values to them from inside or outside the function. If a variable is assigned within a function, it is treated by default as a local variable. Therefore, when you uncomment the line, you are trying to reference the local variable c before any value has been assigned to it.

If you want the variable c to refer to the global c = 3 assigned before the function, put

global c

as the first line of the function.

As for python 3, there is now

nonlocal c

that you can use to refer to the nearest enclosing function scope that has a c variable.



Related Topics



Leave a reply



Submit