Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Globals in nested functions

3 views
Skip to first unread message

jm.s...@gmail.com

unread,
Jun 21, 2007, 7:06:50 AM6/21/07
to
def f():
a = 12
def g():
global a
if a < 14:
a=13
g()
return a

print f()

This function raises an error. Is there any way to access the a in f()
from inside g().

I could find few past discussions on this subject, I could not find
the simple answer whether it is possible to do this reference.

-
Suresh

Duncan Booth

unread,
Jun 21, 2007, 8:01:16 AM6/21/07
to
"jm.s...@no.spam.gmail.com" <jm.s...@gmail.com> wrote:

'global' means global to the module, it prevents the lookup happening in
current or nested scopes.

Simple answer:

You can access an object referenced by a nested scope variable and you
can mutate the object accessed in that way, but you cannot rebind the
name to a different object without resorting to hackery.

To get the effect you want, simply use a mutable object:

>>> def f():
class v:


a = 12
def g():

if v.a < 14:
v.a=13
g()
return v.a

>>> f()
13

and as soon as the code starts looking at all complex, refactor that so
the class is the thing you interact with:

>>> class F(object):
def g(self):
if self.a < 14:
self.a = 13
def __call__(self):
self.a = 12
self.g()
return self.a

>>> f = F()
>>> f()
13

Bjoern Schliessmann

unread,
Jun 21, 2007, 9:45:35 AM6/21/07
to
jm.s...@no.spam.gmail.com wrote:

> def f():
> a = 12
> def g():
> global a
> if a < 14:
> a=13
> g()
> return a
>
> print f()
>
> This function raises an error. Is there any way to access the a in
> f() from inside g().

Yes. Pass it to g when calling the latter and let g return the
result.

def f():
a = 12

def g(parm):
if parm < 14:
return 13
else:
return a

a = g(a)
return a

print f()

Strange refactoring though.

Regards,


Björn

--
BOFH excuse #400:

We are Microsoft. What you are experiencing is not a problem; it is
an undocumented feature.

Stef Mientki

unread,
Jun 21, 2007, 1:41:05 PM6/21/07
to

As I'm struggling with this myself at the moment,
this will do the job:

def f():
global a
a = 12

cheers,
Stef Mientki

Neil Cerutti

unread,
Jun 21, 2007, 2:48:19 PM6/21/07
to

Python's scoping rules don't allow this. But you can 'box' the
value into a list and get the intended effect.

def f():
a = [12]
def g():

if a[0] < 14:
a[0] = 13
g()
return a[0]

You'll get better results, in Python, by using a class instances
instead of closures. Not that there's anything wrong with Python
closures, but the scoping rules make some fun tricks too tricky.

--
Neil Cerutti

0 new messages