473,387 Members | 1,637 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,387 software developers and data experts.

proc A def/calls proc B: variable scoping rules.

Can anyone explain why "begin B: 123" prints, but 456 doesn't?

$ /usr/bin/python2.3 x1x2.py
begin A:
Pre B: 123 456
begin B: 123
Traceback (most recent call last):
File "x1x2.py", line 13, in ?
A()
File "x1x2.py", line 11, in A
B()
File "x1x2.py", line 7, in B
print "begin B:",x1,x2
UnboundLocalError: local variable 'x2' referenced before assignment
$ cat x1x2.py
#!/usr/bin/env python
def A():
print "begin A:"
x1=123;
x2=456;
def B():
print "begin B:",x1,x2
x2 = x2 - 1; # comment out this line and script x1x2 magically
works!!
print "end B:",x1,x2
print "Pre B:",x1,x2
B()
print "end A:",x1,x2
A()

$ /usr/bin/python2.3
Python 2.3.4 (#1, Mar 10 2006, 06:12:09)
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

$ /usr/bin/python2.3 -V
Python 2.3.4

$ /usr/local/bin/python2.4 -V
Python 2.4.2
$ /usr/local/bin/python2.4 x1x2.py
begin A:
Pre B: 123 456
begin B: 123
Traceback (most recent call last):
File "x1x2.py", line 13, in ?
A()
File "x1x2.py", line 11, in A
B()
File "x1x2.py", line 7, in B
print "begin B:",x1,x2
UnboundLocalError: local variable 'x2' referenced before assignment

# I compiled up 2.4 from the FC4 source, but 2.3 was from SL4.3
$ python -V
Python 2.4.2
$ python
Python 2.4.2 (#1, Aug 15 2006, 21:51:33)
[GCC 3.4.5 20051201 (Red Hat 3.4.5-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
$

Aug 15 '06 #1
9 1910
NevilleDNZ wrote:
Can anyone explain why "begin B: 123" prints, but 456 doesn't?

$ /usr/bin/python2.3 x1x2.py
begin A:
Pre B: 123 456
begin B: 123
Traceback (most recent call last):
File "x1x2.py", line 13, in ?
A()
File "x1x2.py", line 11, in A
B()
File "x1x2.py", line 7, in B
print "begin B:",x1,x2
UnboundLocalError: local variable 'x2' referenced before assignment
$ cat x1x2.py
#!/usr/bin/env python
def A():
print "begin A:"
x1=123;
x2=456;
def B():
print "begin B:",x1,x2
x2 = x2 - 1; # comment out this line and script x1x2 magically
works!!
Hardly surprising. This statement is an assignment to x2, which
therefore becomes local to the function. Since no previous value has
been assigned to this local, the exception occurs.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Aug 16 '06 #2

Steve Holden wrote:
Hardly surprising. This statement is an assignment to x2, which
therefore becomes local to the function. Since no previous value has
been assigned to this local, the exception occurs.
But: In this case the assignment is never reached.... eg..
#!/usr/bin/env python
def A():
print "begin A:"
x1=123
x2=456
def B():
print "begin B:",x1,x2
if False: x2 = x2 + 210 # Magically disappears when this line is
commented out.
print "end B:",x1,x2
print "pre B:",x1,x2
B()
print "end A:",x1,x2
A()

# same error message...
$ ./x1x2.py
begin A:
Pre B: 123 456
begin B: 123
Traceback (most recent call last):
File "./x1x2.py", line 13, in <module>
A()
File "./x1x2.py", line 11, in A
B()
File "./x1x2.py", line 7, in B
print "begin B:",x1,x2
UnboundLocalError: local variable 'x2' referenced before assignment

I guess it is something to do with the scoping of duck typing.

I WAS expecting that the A.x2 was visable until x2 is somehow (by
assignment) made local. I guess I am learning that what you do to a
variable in the middle of scope (even in an unreachable statement)
effects the entire scope. Is there anyway to force x2 to be A.x2
(without declaring it to be a global.x2)? Maybe I can put it into a
A.local class...

The result sh/could be:
begin A:
pre B: 123 456
begin B: 123 456
end B: 123 666
end A: 123 666

ThanX
NevilleD

Aug 16 '06 #3
NevilleDNZ wrote:
Steve Holden wrote:
>>Hardly surprising. This statement is an assignment to x2, which
therefore becomes local to the function. Since no previous value has
been assigned to this local, the exception occurs.


But: In this case the assignment is never reached.... eg..
Doesn't matter. It's not the *execution* of the assignment that makes
the name local, it's the *existence* of the assignment, detected by
static code analysis.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Aug 16 '06 #4
I inserted x1,x2 into A to force a wider scope and it works.

#!/usr/bin/env python
def A():
print "begin A:"
A.x1=123;
A.x2=456;
def B():
print "begin B:",A.x1,A.x2
A.x2 = A.x2 + 210; # problem gone.
print "end B:",A.x1,A.x2
print "pre B:",A.x1,A.x2
B()
print "end A:",A.x1,A.x2
A()

$ ./z1z2.py
begin A:
pre B: 123 456
begin B: 123 456
end B: 123 666
end A: 123 666

$ python -V
Python 2.5b3

I checked: This method even handles recursion giving a new instance of
A.x2 each call.
Is this the official way to scope/inherit scopes in sub procs?

ThanX
NevilleD

Aug 16 '06 #5
NevilleDNZ wrote:
I inserted x1,x2 into A to force a wider scope and it works.

#!/usr/bin/env python
def A():
print "begin A:"
A.x1=123;
A.x2=456;
def B():
print "begin B:",A.x1,A.x2
A.x2 = A.x2 + 210; # problem gone.
print "end B:",A.x1,A.x2
print "pre B:",A.x1,A.x2
B()
print "end A:",A.x1,A.x2
A()

$ ./z1z2.py
begin A:
pre B: 123 456
begin B: 123 456
end B: 123 666
end A: 123 666

$ python -V
Python 2.5b3

I checked: This method even handles recursion giving a new instance of
A.x2 each call.
Is this the official way to scope/inherit scopes in sub procs?
No. It's too horrible to contemplate without getting mild feelings of
nausea. What exactly is it you are tring to achieve here (since I assume
your goal wasn't to make me feel sick :-)?

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Aug 16 '06 #6

Steve Holden wrote:
No. It's too horrible to contemplate without getting mild feelings of
nausea. What exactly is it you are tring to achieve here (since I assume
your goal wasn't to make me feel sick :-)?
It is part of an algorithum:
#!/usr/bin/env python
def A(k, x1, x2, x3, x4, x5):
def B():
k = k - 1;
B.out=A.out=A(k, B, x1, x2, x3, x4)
return B.out
if k <= 0: A.out = x4 + x5
else: B()
return A.out
print A(10, 1, -1, -1, 1, 0);
# correct output is -67

The scope of k remains one problem, as it is passed as an argument to
A.

I think x1,x2,x3,x4 are meant to be lambdas as well... :-)
N

Aug 16 '06 #7
On Tue, 15 Aug 2006 18:38:49 -0700, NevilleDNZ wrote:
UnboundLocalError: local variable 'x2' referenced before assignment

I guess it is something to do with the scoping of duck typing.
Er, no. Scoping and duck typing are completely different concepts.

Scoping refers to the idea of where a variable name is valid.

Duck typing refers to the concept that one should not explicitly test for
the type of objects (the variable's content), but should rely on the
object being able to handle the methods you call ("if it quacks like a
duck, and swims like a duck, we can treat it as if it were a duck; if an
object contains the same methods as a string, we should treat it as if it
were a string").

The two concepts are unrelated.

You're error is precisely what the exception says: according to Python's
scoping rules, x2 is a local variable, but you've tried to read the value
of that name before setting it.
I WAS expecting that the A.x2 was visable until x2 is somehow (by
assignment) made local.
You expected wrong.

Here's some sample code that shows the scoping rules in action:
# scope.py
# globals
a, b, c = "global a", "global b", "global c"

def func0():
print " ", a, b, c

def func1():
# define only a as a local variable
a = "local a in func1"
print " ", a, b, c
def func2():
# define both a and b as locals
a = "local a in func2"
b = "local b in func2"
print " ", a, b, c

def func3():
# define a as a local, but in the wrong place
try:
print " ", a, b, c
except UnboundLocalError:
print "Attempt to access the value of a local " \
"variable before setting it."
a = "local a in func3"
print " ", a, b, c

def func4():
# uses nested functions
a = "local a in func4"
print " ", a, b, c

def func5():
b = "local b in func5"
print "Calling nested function func5:"
print " ", a, b, c

def func6():
global a, b
print "Calling nested function func6:"
print " ", a, b, c

func5()
func6()

for function in (func0, func1, func2, func3, func4):
print "Calling function %s:" % function.__name__
function()

# end scope.py

Basically, when you access a variable name on the left hand side of an
assignment (e.g. "a = 1") ANYWHERE in a function, that name is local to
that function UNLESS it has been declared global.

When you access a variable name as the right hand side of an assignment,
or as an expression (e.g. "print a"), Python searches for it following the
scoping rules: first it searches for it in the function's local variables,
then the local variables of the next higher scope, and so on, and finally
it searches for it amongst the globals (which is the top-level scope of
everything).

Play around with the code and see if it makes sense.

--
Steven D'Aprano

Aug 16 '06 #8
On Tue, 15 Aug 2006 20:28:34 -0700, NevilleDNZ wrote:
>
Steve Holden wrote:
>No. It's too horrible to contemplate without getting mild feelings of
nausea. What exactly is it you are tring to achieve here (since I assume
your goal wasn't to make me feel sick :-)?

It is part of an algorithum:
Every piece of code is part of an algorithm. What is the algorithm
supposed to accomplish, apart from giving people a headache?

I'm not saying that what you've done can't ever be useful, but I'm with
Steve on this one. Yuck.
--
Steven D'Aprano

Aug 16 '06 #9

Steven D'Aprano wrote:
Basically, when you access a variable name on the left hand side of an
assignment (e.g. "a = 1") ANYWHERE in a function, that name is local to
that function UNLESS it has been declared global.
ThanX Steven, I am still getting used to python scoping rules. I didn't
realise that using a variable on the left affected the variables on the
right. I WAS trying to avoid making the variable GLOBAL, and just pick
it out of the superior proc's scope.
>
When you access a variable name as the right hand side of an assignment,
or as an expression (e.g. "print a"), Python searches for it following the
scoping rules: first it searches for it in the function's local variables,
then the local variables of the next higher scope, and so on, and finally
it searches for it amongst the globals (which is the top-level scope of
everything).
I am more used to nested scopes, as in pascal/C.
>
Play around with the code and see if it makes sense.
I will certainly dabble with your example further.

Many ThanX
NevilleD

BTW: here is my poor attempt at porting the "man boy test" algorithum
to python. As you can see in python I am still a boy... :-)

$ cat ./man_boy_test.py
#!/usr/bin/env python
def A(k, x1, x2, x3, x4, x5):
A.k=k
def B():
A.k = A.k - 1
B.out=A.out=A(A.k, B, x1, x2, x3, x4)
return B.out
if A.k <= 0: A.out = x4() + x5()
else: B()
return A.out
if A(10,lambda:1,lambda:-1,lambda:-1,lambda:1,lambda:0)==-67:
print "man"
else:
print "boy"
# end man_boy_test.py

$ ./man_boy_test.py
boy

Aug 16 '06 #10

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

Similar topics

68
by: Marco Bubke | last post by:
Hi I have read some mail on the dev mailing list about PEP 318 and find the new Syntax really ugly. def foo(x, y): pass I call this foo(1, 2), this isn't really intuitive to me! Also I...
7
by: Michael G | last post by:
I am a little surprised that the following that $x is visible outside of the scope in which it is (?)defined(?) (not sure if that is the correct term here). I am trying to find where in the php...
166
by: Graham | last post by:
This has to do with class variables and instances variables. Given the following: <code> class _class: var = 0 #rest of the class
6
by: Marcia Hon | last post by:
Hi, I have a function that has a counter variable that I increment. It increments after a function call within the first function. Somehow, when I return from the second function to increment...
8
by: Florian Daniel Otel | last post by:
Hello all, As the subject says, I am a newcomer to Python and I have a newcomer question wrt namespaces and variable scope. Obviously, I might be missing smth obvious, so TIA for the patience...
3
by: morris.slutsky | last post by:
So every now and then I like to mess around with hobby projects - I often end up trying to write an OpenGL video game. My last attempt aborted due to the difficulty of automating game elements and...
17
by: Chad | last post by:
The following question stems from Static vs Dynamic scoping article in wikipedia. http://en.wikipedia.org/wiki/Scope_(programming)#Static_versus_dynamic_scoping Using this sites example, if I...
10
by: John Passaniti | last post by:
(Note: This is not the same message I posted a week or so ago. The problem that prevented my previous attempt to work was a silly error in the template system I was using. This is a problem...
2
by: Joshua Kugler | last post by:
I am trying to use lamdba to generate some functions, and it is not working the way I'd expect. The code is below, followed by the results I'm getting. More comments below that. patterns = (...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.