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



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

.



Relevant Pages

  • Re: Is there any sense in using final keyword in catch block?
    ... I think the point of a final qualifier is to reassure the programmer that it won't change unexpectedly - it's an aid to reasoning about the code. ... local variables can only be accessed from inside the method they're local to; that's a much smaller body of code that the programmer has to keep in mind to know everything about the variable's use. ... If your method is big enough that making its locals final is helping you, then you need to split it up into multiple smaller methods. ...
    (comp.lang.java.programmer)
  • Re: Long.valueOf(long) CodeAttribute max_locals wrong?
    ... final int offset = 128; ... view" of local variables, or with the JVM view of local variables? ... Compiling code with debug information should provide proper initialization code for the final int offset, because debuggers may access the names and/or values of the local variables. ... public class Locals { ...
    (comp.lang.java.machine)
  • Re: Local variables controversial?
    ... >>> if you keep them on the stack the stack is minimally 4 deep, ... >> Graphics always comes up when locals are discussed. ... >> that don't ever require substandial stack thrashing OR local variables. ...
    (comp.lang.forth)
  • RfD: Enhanced local variable syntax
    ... The current LOCALS| ... ... to be initialised from the data stack. ... local buffers are much faster than using ALLOCATE ... The following syntax for local arguments and local variables is ...
    (comp.lang.forth)
  • Re: Eval needs explicit self for accessor methods?
    ... locals declaration causes unexpected behavior: ... Local variables *created* inside a block are *not* visible outside the block. ... The third rule is the one that throws everyone because most programmers tend to think of block arguments as formal arguments that shadow any similarly named variables outside the block but this is incorrect (in Ruby). ... Block arguments behave like *local* variables so if a block argument has the same name as a variable in the enclosing scope then a new local variable is *not* created. ...
    (comp.lang.ruby)

Loading