See the following example:
#########
def tutu():
def toto():
print a
a = 4
print a
a=2
toto()
tutu()
##########
I obtain the following error:
"UnboundLocalError: local variable 'a' referenced before assignment"
This is because Python looks in the local context before looking in the
global context.
The use of "global a" in toto() does not help because global allows to force
Python to look for the variable at the module level.
So, how to share a variable between intricated functions?
Thanks a lot
Julien
--
python -c "print ''.join([chr(154 - ord(c)) for c in '*9(9&(18%.\
9&1+,\'Z4(55l4('])"
"When a distinguished but elderly scientist states that something is
possible, he is almost certainly right. When he states that something is
impossible, he is very probably wrong." (first law of AC Clarke)
> Hi everybody,
>
> See the following example:
>
> #########
> def tutu():
>
> def toto():
>
> print a
> a = 4
> print a
>
> a=2
> toto()
>
> tutu()
> ##########
>
> I obtain the following error:
> "UnboundLocalError: local variable 'a' referenced before assignment"
>
> This is because Python looks in the local context before looking in the
> global context.
>
> The use of "global a" in toto() does not help because global allows to
> force Python to look for the variable at the module level.
>
> So, how to share a variable between intricated functions?
You could use a class :)
Another often used trick is to have a mutable container-object, like this:
def tutu():
a = [2]
def toto():
a[0] = 4
toto()
Diez
nonlocal a #note: this requires a rather recent version of python
> print a
> a = 4
> print a
>
> a=2
> toto()
>
> tutu()
> ##########
>
> I obtain the following error:
> "UnboundLocalError: local variable 'a' referenced before assignment"
>
> This is because Python looks in the local context before looking in the
> global context.
>
> The use of "global a" in toto() does not help because global allows to force
> Python to look for the variable at the module level.
>
> So, how to share a variable between intricated functions?
Details: http://www.python.org/dev/peps/pep-3104/
Cheers,
Chris
--
http://blog.rebertia.com
> Hi everybody,
>
> See the following example:
>
> #########
> def tutu():
>
> def toto():
>
> print a
> a = 4
> print a
>
> a=2
> toto()
>
> tutu()
> ##########
>
> I obtain the following error:
> "UnboundLocalError: local variable 'a' referenced before assignment"
>
> This is because Python looks in the local context before looking in the
> global context.
>
> The use of "global a" in toto() does not help because global allows to
> force Python to look for the variable at the module level.
>
> So, how to share a variable between intricated functions?
This limitation is removed in Python 3 with the 'nonlocal' statement:
>>> def outer():
... def inner():
... nonlocal a
... print(a)
... a = 4
... print(a)
... a = 2
... inner()
... print(a)
...
>>> outer()
2
4
4
Peter
Generally your purpose as a programmer is to write the least intricate
code. Because the less tricky it is, the more readable it becomes and
also the bug count decreases.
So probably a better solution is to just use the normal function
semantics: you pass them an argument and you take an argument as
return value. Such return value will be the new version of the value
you talk about.
Python3+ has the "nonlocal" statement that may do what you ask for.
But as many other things in Python it must be used with judgment, to
avoid writing intricate code.
Bye,
bearophile
> So probably a better solution is to just use the normal function
> semantics: you pass them an argument and you take an argument as
> return value. Such return value will be the new version of the value
> you talk about.
Thanks for your answer.
Yes, it is better like this. My problem is that I cannot get the return
values of the function and affect it to some variable, because the function
is called via a "signal-slot" connection of PyQt4, not by an explicit
inline function call.
For example:
#########
def tutu():
def toto():
print a
a = 4
print a
a=2
# ...
# definition of some graphical QPushButton "button"
# ...
# ...
self.connect( button, SIGNAL( "clicked" ), toto )
tutu()
##########
Then, as advised Diez, perhaps the best solution is to have "true" global
variables by using a class and defining the variable a as a member self.a
of the class. By doing like this, a will be known everywhere.
Or, as Bearophile suggested, you could use the standard way of passing
arguments into a function:
>>> def tutu():
... a = 2
... def toto(a=a):
... print 'toto', a
... a = 4
... print 'toto', a
... print 'tutu', a
... toto()
... print 'tutu', a
...
>>> tutu()
tutu 2
toto 2
toto 4
tutu 2
You could also just do 'toto(a)', but as you're trying to create a
closure here, binding the external scope 'a' to toto via the default
argument will (probably) do what you need.
When you need a writable bound variable inside a closure, I prefer this
idiom:
def foo():
def bar():
print bar.a
bar.a = 4
print bar.a
bar.a = 2
bar()
Python 3's nonlocal is obviously much more elegant.
Cheers,
Jason.