Asking for Help/Why is my global not assigned?¶
Legacy Wiki Page
This page was migrated from the old MoinMoin-based wiki. Information may be outdated or no longer applicable. For current documentation, see python.org.
Asking for Help: Why is my global not assigned?¶
The following puzzles me: Both a and b are globals. Both are assigned an initial value in fun(). But b is considered unassigned in fun1().
1 def fun():
2 global a,b
3 a = [0]*1
4 b = 0
5 fun1()
6
7 def fun1():
8 a[0] += 1
9 print('a[0]: ', a[0])
10 b += 1
11 print('b: ', b)
12
13
14 fun()
15
16 b += 1
17 UnboundLocalError: local variable 'b' referenced before assignment
The purpose of global{.backtick} is to indicate which names are global in that specific part of a program. So, although you have indicated that b{.backtick} is global in fun{.backtick}, you still need to indicate that b{.backtick} is global in fun1{.backtick}. Otherwise, Python doesn’t know where to get b{.backtick} from. It’s actually slightly more complicated than this; for more, see below.
Now, you do manage to get away with not declaring a{.backtick} as global in both functions. The reason for this is that you aren’t changing what a{.backtick} refers to, but are instead modifying an item (or element) in what a{.backtick} refers to (a list). So, Python deduces that a{.backtick} is a global and doesn’t change its mind about it: a{.backtick} isn’t itself made to refer to something else in fun1{.backtick}, so any reference to a{.backtick} is always to a global object.
So, back to the problem with b{.backtick}. When Python compiles fun1{.backtick}, it has to consider that b{.backtick} itself is being assigned to and that there’s no global{.backtick} declaration for b{.backtick} in fun1{.backtick}. So, Python then believes b{.backtick} to be a local. But then, in the assignment itself, it has to get the value of b{.backtick} (think of it as b + 1; b = <result>{.backtick}), and at that point there is no such local, so you get the error.
In short, Python has to decide whether a name is local or global and stick with that decision for every mention of that name in a function: it can’t switch between the two since it has to generate code that builds on the assumption that a name is always local or always global in that function. So you should always declare names as global in any function where you are assigning to them as globals. – PaulBoddie 2012-04-24 20:57:57