Dumb newbie back in shell

M

MartinRinehart

OK, it's a scripting language.
.... os.remove('tokeneizer.pyc')
.... reload( tokeneizer )
.... tokeneizer.tokenize('sample_decaf.d')
....
But that gets me to:

.... line 110, in get_toks
UnboundLocalError: local variable 'line_ptr' referenced before
assignment

Here's a bit of the code, with line #s

....
68 global line_ptr
69 global char_ptr
....
75 line_ptr = 0
76 char_ptr = 0
....
109 def get_toks( text ):
110 while line_ptr < last_line:
....
So when is a global var global?
 
M

Marc 'BlackJack' Rintsch

But that gets me to:

... line 110, in get_toks
UnboundLocalError: local variable 'line_ptr' referenced before
assignment

Here's a bit of the code, with line #s

...
68 global line_ptr
69 global char_ptr
...
75 line_ptr = 0
76 char_ptr = 0
...
109 def get_toks( text ):
110 while line_ptr < last_line:
...
So when is a global var global?

When you declare it ``global`` *in the function*. ``global`` on module
level has no effect. IMHO that should emit at least a warning…

Ciao,
Marc 'BlackJack' Rintsch
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
OK, it's a scripting language.

For which definition of "scripting language" ?-)
... os.remove('tokeneizer.pyc')
... reload( tokeneizer )
... tokeneizer.tokenize('sample_decaf.d')
...

But that gets me to:

... line 110, in get_toks
UnboundLocalError: local variable 'line_ptr' referenced before
assignment

Here's a bit of the code, with line #s

...
68 global line_ptr
69 global char_ptr
...
75 line_ptr = 0
76 char_ptr = 0
...
109 def get_toks( text ):
110 while line_ptr < last_line:
...
So when is a global var global?

Short answer : never !-)

Long answer:

First point: "global" really means "module level" - there's no
"application global" namespaces.

Second point: every name declared as the top-level is global - according
to the above definition. So there's no need to declare them as such. The
only place where you need the global statement is when you want to
rebind a module-level name from within a function. And it's in this
function that you need to declare the name as global.

FWIW, this is documented.

Last point: Python is not C, and it definitively doesn't have pointers.
Trying to write C in Python is a waste of time and an experiment in
frustration (just like trying to write language XXX in language YYY for
any distinct values of XXX and YYY).

HTH
 
M

MartinRinehart

Thanks, Marc.

However, here's the little tester I wrote:

# t.py - testing

global g
g = 'global var, here'

def f():
print g

f()

It prints 'global var, here,' not an error message. Wassup?
 
P

Peter Otten

MartinRinehart said:
However, here's the little tester I wrote:

# t.py - testing

global g
g = 'global var, here'

def f():
print g

f()

It prints 'global var, here,' not an error message. Wassup?

Try it again with a modified f():

def f():
print g
g = 42

In Python variables that are assigned to in a function are
function-local by default.

Peter
 
M

MartinRinehart

Not trying to write C, I'm trying to write Decaf, a language I've
designed (see www.MartinRinehart.com for more) but which doesn't
exist. Got to code the first bit in something. Later I can write Decaf
in Decaf. Chose Python as it looked like a faster write (learning
curve included) than C or C++.

Python is commonly called a "scripting" language because of its use as
one of the Ps in the LAMP stack. I'm using it as a general-purpose
programming language with the neat feature of being able to write
scripts in its own console.
 
D

Dennis Lee Bieber

Thanks, Marc.

However, here's the little tester I wrote:

# t.py - testing

global g
g = 'global var, here'

def f():
print g

f()

It prints 'global var, here,' not an error message. Wassup?
"g" doesn't appear on the LHS of an assignment statement IN the
function.

And, as mentioned, that "global" statement is a no-op where you have
it placed.

Names on the LHS, in the absence of a function level "global",
become local to the function -- this is determined when the function
object is compiled; then when run any RHS usage prior to the LHS becomes
an error.

RHS usage only doesn't require "global", the look-up system will
scan the function locals and then move out to the module level names.
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
M

MartinRinehart

Peter,

question is, why did the first one work? In my real code I've got
module-level vars and an error msg trying to use them in a function.
In my test example I've got them accessed from within a function w/o
error message.

I am confused.

Martin
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
Not trying to write C,

I meant "trying to use Python like it was C" - but I guess it doesn't
matter that much !-)
I'm trying to write Decaf, a language I've
designed (see www.MartinRinehart.com for more) but which doesn't
exist. Got to code the first bit in something. Later I can write Decaf
in Decaf. Chose Python as it looked like a faster write (learning
curve included) than C or C++.
Indeed.

Python is commonly called a "scripting" language because of its use as
one of the Ps in the LAMP stack.

Now that's a definition I never heard before !-)
I'm using it as a general-purpose
programming language with the neat feature of being able to write
scripts in its own console.

Seriously, the Python shell is not meant to write serious code. I
sometimes use it like a, well, shell (mostly to do quick maintenance on
Zope apps - just like you'd fire a command-line SQL client to inspect
and fix a problem on your favorite RDBMS), but the main use of it is
still to quickly explore APIs, corner cases etc... Now perhaps I'm
misunderstanding you, but your questions about module reloading are IMHO
a sign your asking to much from the Python REPL.

Anyway, welcome on board !-)

Regards
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
(Martin, please, don't top post - fixed)
>
> question is, why did the first one work?

The answer is just above.
> In my real code I've got
> module-level vars and an error msg trying to use them in a function.
> In my test example I've got them accessed from within a function w/o
> error message.
>
> I am confused.


In the fist you're not rebinding the g. And FWIW, this is a FAQ.
 
M

MartinRinehart

I'm less confused. If someone can explain the wisdom of this design,
I'd be grateful.

If someone can explain why the following compiles successfully, I'd be
even more grateful:

def get_toks( text ):
global line_ptr, last_line
while line_ptr < last_line:
while char_ptr < len(text[line_ptr]):
if matches_EOI():
tokens.append( Token(EOI) )
elif matches_EOL():
tokens.append( Token(EOL) )
line_ptr += 1
char_ptr = 0

Shouldn't "char_ptr" be flagged as an error, appearing in line 4
before being a lhs in the last line?

Martin
 
J

J. Clifford Dyer

The code you just posted doesn't compile successfully.

However, in your code, you probably have char_ptr defined at the module level, and you're confused because you didn't declare it as global. Am I right? My crystal ball has a smudge on it, but I think I can still see okay.

You can still reference module level variables that aren't declared as global, but you can't assign to them. Or rather, when you try to, you create a new local variable that shadows the global one.

So the first time through, your char_ptr in the while expression is a module level variable, but the second time through, it references a local variable, because it has now been defined.

Cheers,
Cliff

I'm less confused. If someone can explain the wisdom of this design,
I'd be grateful.

If someone can explain why the following compiles successfully, I'd be
even more grateful:

def get_toks( text ):
global line_ptr, last_line
while line_ptr < last_line:
while char_ptr < len(text[line_ptr]):
if matches_EOI():
tokens.append( Token(EOI) )
elif matches_EOL():
tokens.append( Token(EOL) )
line_ptr += 1
char_ptr = 0

Shouldn't "char_ptr" be flagged as an error, appearing in line 4
before being a lhs in the last line?

Martin

Peter,

question is, why did the first one work? In my real code I've got
module-level vars and an error msg trying to use them in a function.
In my test example I've got them accessed from within a function w/o
error message.

I am confused.

Martin
 
C

Chris Mellon

The code you just posted doesn't compile successfully.

It *compiles* fine, but it'll raise an error when run.
However, in your code, you probably have char_ptr defined at the module level, and you're confused because you didn't declare it as global. Am I right? My crystal ball has a smudge on it, but I think I can still see okay.

I assume that's what he think he's seeing also.
You can still reference module level variables that aren't declared as global, but you can't assign to them. Or rather, when you try to, you create a new local variable that shadows the global one.

No, the determination of what names are local and which are global
happens at compile time. The code as posted will not run correctly. It
could run if it weren't in a function and were executed in global
scope.

What's probably happening is that line_ptr < last_line is not true and
the body of the function isn't executed at all. The unbound local
exception is a runtime error that occurs when the local is accessed,
not when the function is compiled.
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
<OT>
Martin, would you _please_ learn to quote properly ? top-posting and
keeping the whole text of the previous posts are two really annoying
practices. TIA
I'm less confused. If someone can explain the wisdom of this design,
I'd be grateful.

Since there's no distinct declarations of names, all names are by
default created in the local namespace when bound in this namespace.
Else you couldn't shadow global names in a local namespace... OTHO, free
variables are looked up in all enclosing namespaces, so in a a
non-nested function, names used but not bound in the local namespace are
looked up in the global one.
If someone can explain why the following compiles successfully, I'd be
even more grateful:

def get_toks( text ):
global line_ptr, last_line
while line_ptr < last_line:
while char_ptr < len(text[line_ptr]):
if matches_EOI():
tokens.append( Token(EOI) )
elif matches_EOL():
tokens.append( Token(EOL) )
line_ptr += 1
char_ptr = 0

FWIW, this code is incomplete. Please post the minimal *working* code
reproducing your problem. Here, I had to define all the missing symbols
to test your script.
Shouldn't "char_ptr" be flagged as an error, appearing in line 4
before being a lhs in the last line?

Note that such errors are raised at runtime, not during compilation
(FWIW, I wonder why, since the use of the name is detected at
compilation IIRC).

The error appears as long as line_ptr < last_line before calling the
function. Now when line_ptr >= last_line, there is no error. So I
conclude that UnboundLocalErrors are not raised until the offending line
is actually executed.

Now while I don't know if it's a bug or a well-defined behaviour (I
almost never rebind globals in functions..), I agree that this is at
least weird since the compilation phase already tags the name as local
wherever it's bound in the function.

Here's a minimal code reproducing the problem:

cnt = 1
test = 1 # set this to 0 to have an UnboundLocalError in wontdo()
retest = 1
def wontdo():
global test
global restest

while test < retest:
while cnt:
cnt = cnt - 1
test += 1


Some guru on this ?


NB : tested with
Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2



(snip)
 
B

Bruno Desthuilliers

J. Clifford Dyer a écrit :
The code you just posted doesn't compile successfully.

However, in your code, you probably have char_ptr defined at the
module level, and you're confused because you didn't declare it as
global. Am I right? My crystal ball has a smudge on it, but I think
I can still see okay.

You can still reference module level variables that aren't declared
as global, but you can't assign to them. Or rather, when you try to,
you create a new local variable that shadows the global one.
>
So the first time through, your char_ptr in the while expression is a
module level variable, but the second time through, it references a
local variable, because it has now been defined.

IIRC, local assignments are detected during compilation - so this is
not how it works...
 
J

J. Clifford Dyer

Delivered-To: (e-mail address removed)
Date: Tue, 11 Dec 2007 08:36:54 -0600
From: "Chris Mellon" <[email protected]>
To: "(e-mail address removed)" <[email protected]>
Subject: Re: Dumb newbie back in shell
In-Reply-To: <[email protected]>
Precedence: list
List-Id: General discussion list for the Python programming language
<python-list.python.org>
List-Unsubscribe: <http://mail.python.org/mailman/listinfo/python-list>,
<mailto:p[email protected]?subject=unsubscribe>
List-Archive: <http://mail.python.org/pipermail/python-list>
List-Post: <mailto:p[email protected]>
List-Help: <mailto:p[email protected]?subject=help>
List-Subscribe: <http://mail.python.org/mailman/listinfo/python-list>,
<mailto:p[email protected]?subject=subscribe>
Errors-To: [email protected]



It *compiles* fine, but it'll raise an error when run.


I assume that's what he think he's seeing also.


No, the determination of what names are local and which are global
happens at compile time. The code as posted will not run correctly. It
could run if it weren't in a function and were executed in global
scope.

What's probably happening is that line_ptr < last_line is not true and
the body of the function isn't executed at all. The unbound local
exception is a runtime error that occurs when the local is accessed,
not when the function is compiled.

Drat! You're right. I tried it in the interactive interpeter, and the function compiled just fine. I tried calling the function and got an "UnboundLocalError." I think I need to go sit in the corner and review the documentation.

Sorry all. Disregard my previous post.

Chris, many thanks for your corrections.

Cheers,
Cliff
 
B

Bruno Desthuilliers

Chris Mellon a écrit :
(snip)
What's probably happening is that line_ptr < last_line is not true
Indeed.

and the body of the function isn't executed at all. The unbound local
exception is a runtime error that occurs when the local is accessed,
not when the function is compiled.

Now since the compiler already detected the name as local, why wait
execution to signal this error ?
 
C

Chris Mellon

Chris Mellon a écrit :
(snip)

Now since the compiler already detected the name as local, why wait
execution to signal this error ?

Because detection assignment to a name in the first AST scan and then
using LOAD_FAST and STORE_FAST for access to and assigning to that
name is a simple, easy thing to implement, while doing execution
analysis to detect that it can't possibly be set before being
referenced is really hard.
 
B

Bruno Desthuilliers

Chris Mellon a écrit :
Because detection assignment to a name in the first AST scan and then
using LOAD_FAST and STORE_FAST for access to and assigning to that
name is a simple, easy thing to implement, while doing execution
analysis to detect that it can't possibly be set before being
referenced is really hard.

Ok, makes sens.

Now nobody should ever rebind a global name anyway !-)
 
M

MartinRinehart

re top posting

Thanks for explaining. google groups hides the quoted text, so I
didn't see it.
 

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
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top