LEGB rule, totally confused ...

S

stef mientki

hello,

I've thought many times I finally understood the import / namespace rules,
but again I'm totally lost :-(

This is my library file

# Module lib_test.py

X = 1

def Init():
global X
X = 3
print 'Init', X

def Run ():
print X <=== UnboundLocalError: local variable
'X' referenced before assignment
X = X + 1
print ' Run', X



And this my main program in another file:

import lib_test
lib_test.Init()
print lib_test.X

lib_test.Run()
print lib_test.X

Why do I get the error ?
Printing isn't assigning anything or am I missing something.
Now if I remove "X = X + 1" I don't get an error ???
Is this a problem of the traceback procedure or the IDE,
or is Python not completely an interpreter, that reads line by line ???

Please explain this to me.

thanks,
Stef Mientki
 
D

Diez B. Roggisch

stef said:
hello,

I've thought many times I finally understood the import / namespace rules,
but again I'm totally lost :-(

This is my library file

# Module lib_test.py

X = 1

def Init():
global X
X = 3
print 'Init', X

def Run ():
print X <=== UnboundLocalError: local variable
'X' referenced before assignment
X = X + 1
print ' Run', X



And this my main program in another file:

import lib_test
lib_test.Init()
print lib_test.X

lib_test.Run()
print lib_test.X

Why do I get the error ?
Printing isn't assigning anything or am I missing something.
Now if I remove "X = X + 1" I don't get an error ???
Is this a problem of the traceback procedure or the IDE,
or is Python not completely an interpreter, that reads line by line ???

Please explain this to me.

This are the scoping-rules of python. A variable name on the left side of an
name-binding/assignment operator (including augmented assignments, vulgo:
+= and brothers) will make the variable name a function-local.

So

x = 10
def foo():
print x
x = 100

makes x a local variable to foo, which of course can't be accessed in

print x

Diez
 
L

Laurent Pointal

stef mientki a écrit :
hello,

I've thought many times I finally understood the import / namespace rules,
but again I'm totally lost :-(

This is my library file

# Module lib_test.py

X = 1

def Init():
global X
X = 3
print 'Init', X

def Run ():
print X <=== UnboundLocalError: local variable
'X' referenced before assignment
X = X + 1
print ' Run', X



And this my main program in another file:

import lib_test
lib_test.Init()
print lib_test.X

lib_test.Run()
print lib_test.X

Why do I get the error ?
Printing isn't assigning anything or am I missing something.

If you use a global to *modify* it, you MUST declare "global X", either
Python consider using a local.
So for your error: at compile time, in Run(), it see that it must use a
local X (because you set it) and generate ad-hoc bytecode, but when
running X is not defined locally, so the error.
Now if I remove "X = X + 1" I don't get an error ???

If you remove the "X =..." statement, then the compiler dont know
a-priori if its local or global, so it search X in both namespaces.
Is this a problem of the traceback procedure or the IDE,
or is Python not completely an interpreter, that reads line by line ???

Its compiled to buyte-code then interpreted from the byte-code.
Please explain this to me.

thanks,
Stef Mientki

A+

Laurent.
 
N

Neil Cerutti

I've thought many times I finally understood the import /
namespace rules, but again I'm totally lost :-(

This is my library file

# Module lib_test.py

X = 1

def Init():
global X
X = 3
print 'Init', X

def Run ():
print X <=== UnboundLocalError: local variable
'X' referenced before assignment
X = X + 1
print ' Run', X

From _Python Language Reference Manual_ see: '4.1 Naming and
Binding' and '6.13 The global statement'.

If a name is bound [assigned] in a block, it is a local
variable of that block.

...

The global statement is a declaration which holds for the
entire current code block. It means that the listed identifiers
are to be interpreted as globals. It would be impossible to
assign to a global variable without global, although free
variables may refer to globals without being declared global.

Since your Init and Run functions both assign (bind) a value to
X, X is assumed to be a local variable unless you say otherwise
with a global statement.

Note that the global statement in Init applies only in Init's
code block. Run must have it's own 'global X' statement, if
applicable.
 
S

Sion Arrowsmith

stef mientki said:
def Run ():
print X <=== UnboundLocalError: local variable
'X' referenced before assignment
X = X + 1

Why do I get the error ?
Printing isn't assigning anything or am I missing something.
Now if I remove "X = X + 1" I don't get an error ???

Several people have already explained the scoping rules acting
here, but let's just look at how that error message is telling
you everything you need to know to fix the problem.

"local variable 'X' referenced before assignment"

"local variable 'X'" immediately tells you that the 'X' in
question is not your global 'X'.

"referenced before assignment": well, 'print X' is surely a
reference to 'X', and 'X = X + 1' is an assignment to it,
and 'print X' appears before 'X = X + 1'. That this is the
key you have confirmed experimentally.

The question to ask here is "Why does Python think 'X' is
local?" Everything else is answered by the error message.
 
S

stef mientki

Sion said:
Several people have already explained the scoping rules acting
here, but let's just look at how that error message is telling
you everything you need to know to fix the problem.

"local variable 'X' referenced before assignment"

"local variable 'X'" immediately tells you that the 'X' in
question is not your global 'X'.

"referenced before assignment": well, 'print X' is surely a
reference to 'X', and 'X = X + 1' is an assignment to it,
and 'print X' appears before 'X = X + 1'. That this is the
key you have confirmed experimentally.

The question to ask here is "Why does Python think 'X' is
local?" Everything else is answered by the error message.
Thanks guys, I beginning to see the light again,
and if X is mutual the story is completely different,
I still have to get used to these differences.

cheers,
Stef Mientki
 
D

Diez B. Roggisch

Thanks guys, I beginning to see the light again,
and if X is mutual the story is completely different,
I still have to get used to these differences.

<nitpicking-for-the-sake-of-the-casual-reader>

That's supposed to be "mutable", not "mutual".

</nitpicking-for-the-sake-of-the-casual-reader>

Diez
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top