473,421 Members | 1,500 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,421 software developers and data experts.

nested function scopes

hi,

i'm having some trouble nesting functions. consider the following:
def h():
x = 1
def g():
print x # ok, x is taken from h
g()

def f():
x = 1
def g():
print x # this is not ok
x = 2 # this implies that x is local to g
g()

h() # ok
f() # UnboundLocalError: local variable 'x' referenced before assignment
when i run this code i get:
1
Traceback (most recent call last):
File "test.py", line 15, in ?
f() # UnboundLocalError: local variable 'x' referenced before assignment
File "test.py", line 12, in f
g()
File "test.py", line 10, in g
print x # this is not ok
UnboundLocalError: local variable 'x' referenced before assignment
how do i declare that x belongs to the parent function, so that i can do
assignments to it? do i have to put it into a compound object?

it would be very handy to be able to do this if i have nested functions
that use a lot of varables. only passing the variables you assign to as
packed compound parameters is a bit ugly, since what subset of all
variables this is might change.

i cannot say i like the python scope rules yet. they probably are
practical, but they seem complicated an unstructured to me.

take for example
class C:
y = 0
def f(self):
print y
which does not work unless y is a global. i understand and agree too why
y is not taken from the instance (self), because of the way classes and
instances relate in python. what i do not understand, is why y is not
taken from C, but from global, when nothing is specified. in the
previous example, with the functions h() and g(), g() took x from h().
why should not f() take y from C?

klem fra nils

--
nils grimsmo <ni*****@idi.ntnu.no>
"why is this thus? what is the reason of this thusness"
- artemus ward
Jul 18 '05 #1
3 2321
Nils Grimsmo wrote:
i'm having some trouble nesting functions. consider the following:
You understand the rules, I think. You just don't like them. The
appropriate koan is "explicit is better than implicit".

I'd use something like this:

class Struct(object):
pass
...
def outer():
shared = Struct()
shared.counter = 1
def inner():
print 'inner says:', shared.counter
shared.counter += 1
inner()
inner()
print 'outer says:', shared.counter
it would be very handy to be able to do this if i have nested
functions that use a lot of variables. only passing the variables
you assign to as packed compound parameters is a bit ugly,
since what subset of all variables this is might change.
Python's goal is to make code more easy to _read_, not _write_.
I find it easier to read the outer function when I know
what might change on me. As my example shows, you needn't
thread all calls with the list of values.

There is another python idea here you haven't yet caught:
You speak of variables, but python only has associations of
names with values. When you think in terms of names and
associations, you may find 'inner's ability to see what 'outer'
is talking about without being able to affect 'outer's
associations reasonable.
i cannot say i like the python scope rules yet. they probably are
practical, but they seem complicated an unstructured to me. Give it time. They are simple when you twist your head just right,
then they will seem completely simple.
class C:
y = 0
def f(self):
print y
Again, "explicit is better than implicit".

Either:
class D(object):
y = "D's y"
def f(self):
print self.y
Or:
class E(object):
y = "E's y"
def f(self):
print E.y

behave as you wish. Bindings first look to the instance and
then the class. Python is quite dynamic. There is, by the way,
a difference between the two above. Ponder the following two
subclasses:

class F(D):
y = "F(D)'s y"

class G(E):
y = "G(E)'s y"

F().f() prints F(D)'s y
G().f() prints E's y

to work in the same was as the two above, but you'd be wrong.
In the previous example, with the functions h() and g(), g()
why should not f() take y from C?

but which class should it choose in my examples? The instance's
exact class? The class in which the method was defined? You
could mean either, and be without a way to specify the other.

Further, you could do this:
y = "global"
class C:
def f(self):
print y

o = C()
o.f()
C.y = "classs variable"
o.f()

Should the second call to o.f() print something different than
the first one?

Anyhow, this is really too long already. I'll just include the
Struct definition I actually use when coding. It uses too much
magic to be clear, but it prints nicely in interactive mode.

This in my "toys.py":

class Struct(object):
def __init__(self, **kw):
self.__dict__.update(kw)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__,
', '.join(['%s=%r' % name_val for
name_val in self.__dict__.items()]))

Then (when I want data types):
import toys
class Holder(toys.Struct): pass # just to give a name

And my example becomes:

def outer():
shared = Holder(counter=1, name='Fred')
def inner():
print 'inner says:', shared
shared.counter += 1
inner()
inner()
print 'outer says:', shared
-Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #2

"Nils Grimsmo" <ni*****@idi.ntnu.no> wrote in message
news:3f********@news.broadpark.no...
hi,

i'm having some trouble nesting functions. consider the following:
def h():
x = 1
def g():
print x # ok, x is taken from h
g()

def f():
x = 1
def g():
print x # this is not ok
x = 2 # this implies that x is local to g
g()

h() # ok
f() # UnboundLocalError: local variable 'x' referenced before assignment .... how do i declare that x belongs to the parent function, so that i can do
assignments to it?
Currently you cannot. As you probably know, 'global' declares that x
belongs to the module so you can assign to as well read it. This fall,
there was an extended discussion on pydev (at least 30 posts, I am sure) on
the subject of extending the idea of global to allow assignment to
intermediate scopes. Would such be desireable? If so, what syntax? See
python.org for B. Cannon's summaries or link to archives. Current bottom
line: no change.
do i have to put it into a compound object?
If compound = mutable collection, yes. Your example revised:

def f():
x = [1]
def g():
print x[0]
x[0] = 2
g()

The ease of doing this and the ugliness or other problems with proposed
alternatives inhibits change.
it would be very handy to be able to do this if i have nested functions
that use a lot of varables. only passing the variables you assign to as
packed compound parameters is a bit ugly, since what subset of all
variables this is might change.
You do not have to 'pass' the compound since you have read access to mutate
it.
i cannot say i like the python scope rules yet. they probably are
practical, but they seem complicated an unstructured to me.
They were simpler before nested scopes were introduced ;-). You can program
without them if you wish.
take for example

class C:
y = 0
def f(self):
print y which does not work unless y is a global. i understand and agree too why
y is not taken from the instance (self), because of the way classes and
instances relate in python. what i do not understand, is why y is not
taken from C, but from global, when nothing is specified. in the
previous example, with the functions h() and g(), g() took x from h().
why should not f() take y from C?


This is a different kettle of fish. Classes, though callable, are not
functions and methods are not nested functions. Neither class nor instance
methods can be called during class construction because neither the class
nor instances thereof even exist. In any case, there is already a mechanism
for accessing class attributes: C.y in this case. Use it.

Terry J. Reedy

Jul 18 '05 #3

Terry Reedy:

Nils Grimsmo:
i'm having some trouble nesting functions. consider the following: [snip] def f():
x = 1
def g():
print x # this is not ok
x = 2 # this implies that x is local to g [snip] how do i declare that x belongs to the parent function, so that i can do assignments to it?


Currently you cannot.


Why not use the old method of passing variables to nested functions:
def f()
x = 1
def g(x=x):
print x
x = 2

Emile van Sebille
em***@fenx.com

Jul 18 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Miki Tebeka | last post by:
Hello, Can anyone explain why: >>> def make_inc(n): s = n def inc(i): s += i return s return inc
6
by: Andy Baker | last post by:
Hi there, I'm learning Python at the moment and trying to grok the thinking behind it's scoping and nesting rules. I was googling for nested functions and found this Guido quote:...
5
by: Dave Benjamin | last post by:
I ran into an odd little edge case while experimenting with functions that create classes on the fly (don't ask me why): >>> def f(x): ... class C(object): ... x = x ... print C.x ......
7
by: block111 | last post by:
Hello, code like this: int f1(int x){ int f2(int y){ return y*y; } if(x > 0) return f2(x);
8
by: Sean Givan | last post by:
Hi. I'm new to Python, and downloaded a Windows copy a little while ago. I was doing some experiments with nested functions, and ran into something strange. This code: def outer(): val =...
37
by: Tim N. van der Leeuw | last post by:
Hi, The following might be documented somewhere, but it hit me unexpectedly and I couldn't exactly find this in the manual either. Problem is, that I cannot use augmented assignment operators...
78
by: Josiah Manson | last post by:
I found that I was repeating the same couple of lines over and over in a function and decided to split those lines into a nested function after copying one too many minor changes all over. The only...
2
by: Johannes Bauer | last post by:
Nick Keighley schrieb: Why is there actually a *need* for nested functions? If functionality of subfunctions which are only locally visible is desired, why not put the nesting function parent...
0
by: Maric Michaud | last post by:
Le Tuesday 12 August 2008 11:29:18 Cousson, Benoit, vous avez écrit : This is a language limitation. This is because nested scope is implemented for python function only since 2.3 allow late...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.