[Tutor] Global var problem
Andrei
project5 at redrival.net
Sat Oct 29 00:14:46 CEST 2005
Hi Nick,
> messing about with classes I've come across something basic that I don't
> understand.
Your issue is not so much with classes as it is with namespaces. You'll
hit the exact same problem with simple functions.
> Take this class
>
> class T:
> def p(self):
> print x
In this case, the Python reference states that if a name (x) is not
found in a block (i.e. inside the p method), it will look in its
surrounding scope for it. That would be the global namespace. Given the
fact that you defined x as a global variable, it finds it there and it
works as expected.
> Now this
> class T:
> def p(self):
> x += 1
> print x
> This outputs
> UnboundLocalError: local variable 'x' referenced before assignment
Here is what the Python docs have to say about assignment:
If the target is an identifier (name):
If the name does not occur in a global statement in the current code
block: the name is bound to the object in the current local
namespace.
In other words, when trying to assign a new value to x, it:
1. looks if x was defined as global *inside the current function/class*
2. sees that it was not defined as global -> therefore it must be local
3. tries to get the value of that local x
4. finds there is no local x -> raises exception
> So I tried this
>
> class T:
> def p(self):
> x += 1
> print x
>
> if __name__ == '__main__':
> global x
> x = 1
> t = T()
> t.p()
> but that gives me the same UnboundLocalError exception.
This second attempt is almost but not quite right: the global statement
is in the wrong place. x is by definition global if defined outside a
class or function, so adding "global" in front of it won't make a
difference. The point is that if you try to assign a value to a global
variable inside a function or class definition, you must tell Python *in
that block* that you want to assign to a global variable, not a local one.
>>> def p():
... global x
... x += 1
>>> x = 5
>>> p()
>>> x
6
Similar problems can occur when defining a function inside another function:
>>> def a():
... aa = 2
... def b():
... print aa # aa in surrounding namespace, not local to b()
... b()
>>> a()
2
>>> def a():
... aa = 2
... def b():
... aa += 1 # in surrounding namespace, not local to b()
... print aa
... b()
>>> a()
UnboundLocalError: local variable 'aa' referenced before assignment
> No doubt the answer is staring me in the face ... but I still can't see it.
I would recommend against using global variables this way (modifying
them inside functions). It's better to use method parameters for input
and the return statement to output any necessary modifications, e.g.:
def p(inp):
output = inp + 1
print output
return output
if __name__ == '__main__':
x = 5
x = p(x)
It would be even better with a decent function name of course :). More
info available in paragraph 4.1 of the Python reference manual.
--
Yours,
Andrei
=====
Mail address in header catches spam. Real contact info:
''.join([''.join(s) for s in zip(
"poet at aao.l pmfe!Pes ontuei ulcpss edtels,s hr' one oC.",
"rjc5wndon.Sa-re laed o s npbi ot.Ira h it oteesn edt C")])
More information about the Tutor
mailing list