global and None

L

Leo Yee

Hi,

I was confused by the global statement and None.
Consider the following code:

--- code begin ---

global g
g=None
def foo():
if g==None:
g=0
foo()

--- code end ---

My purpose is to init g. This is very useful when we cannot construct a
global variable.
But what I got was:
UnboundLocalError: local variable 'g' referenced before assignment

So I try to solve the problem in this way:
--- code begin ---

global g
g=None
def foo():
global g
if g==None:
g=0
foo()

--- code end ---

And it works but the python documentation told me the following:
"Names listed in a global statement must not be defined as formal parameters
or in a for loop control target, class definition, function definition, or
import statement. "

Does anyone know what I should do to solve this problem? Thanks in advance.

Leo Yee
 
M

Martin v. Loewis

Leo said:
Does anyone know what I should do to solve this problem? Thanks in advance.

The global declaration must go in each function that uses the global
variable, and not in the global namespace defining the variable (in
the global namespace, it is clear that the variable is global, so
no need to declare that).

Regards,
Martin
 
F

Francis Avila

Leo Yee wrote in message ...
My purpose is to init g. This is very useful when we cannot construct a
global variable.

Like when? And why?
But what I got was:
UnboundLocalError: local variable 'g' referenced before assignment

Yes; the Python bytecode compiler assumes g is a local unless you specify
otherwise (with the global statement). So when g is referenced, it doesn't
yet exist in the local namespace, even though Python looks for it there.
Hence the error.

Your first global is redundant, because you're already in the global
namespace.
So I try to solve the problem in this way:
--- code begin ---

global g
g=None
def foo():
global g
if g==None:
g=0
foo()

--- code end ---

And it works but the python documentation told me the following:
"Names listed in a global statement must not be defined as formal parameters
or in a for loop control target, class definition, function definition, or
import statement. "

Actually, I've looked at this closely, and thought about it a bit, and I'm
not sure I understand what the docs mean. Here are my guesses:

"formal parameters"
def foo(a=1):
global a

SyntaxError: name 'a' is local and global ("<stdin>", line ?)

Ok, no doubt there.
....
"for loop control target" I believe means you can't do the following:

def foo():
global i
for i in range(10):
pass

However, you *can* do it, and section 6.3 (assignment statements), where
target_list semantics are expounded, allows it:
"""
Assignment of an object to a single target is recursively defined as
follows.
- If the target is an identifier (name):

+ If the name does not occur in a global statement in the current code
block: the name is bound to the object in the current local namespace.

+ Otherwise: the name is bound to the object in the current global
namespace.
"""
Python bug or doc bug in "global"? Or do I misunderstand?


....
moving on: "class definition, function definition"
def bar():
global foo
class/def foo(object):
pass
???
This is currently legal, and works AFAICT. Why should it be prohibited,
aside from being dangerous and abusive?

....
"import statement"
Same thing:
def foo():
global re
import re

foo() # imports re globally.

Currently possible, ugly, and dangerous, but prohibited?
Does anyone know what I should do to solve this problem? Thanks in advance.

What problem? The way you use global doesn't fall under any of these cases
it prohibits. Aside from that, all the cases it prohibits work just fine.

BTW, your code should be:

g = None
def foo():
global g
if g == None:
g = 0

Notice, no 'global g' at the top.

This is why global was made, you know. You're using it properly. Whether
you should be using globals, however, is another story ;)
 
P

Paul McGuire

Francis Avila said:
Leo Yee wrote in message ...

Like when? And why?

One reason is to do late construction/initialization, or lazy
initialization. If an object is very time-consuming to construct, don't
create it at import time, wait until it is actually used. Once created,
save it in a global so that you don't have to re-create it every time.

This is sort of a quick-and-dirty singleton pattern. I do a very similar
thing to construct my pyparsing grammar *once*, then save it in the global
and re-reference it on subsequent calls.

sqlGrammar = None
def getSQLGrammar():
global sqlGrammar
if sqlGrammar is None:
# construct SQL grammar - this only needs to happen once
sqlGrammar = CaselessLiteral("select") + <blah, blah, blah>
return sqlGrammar

def test( sqlstring ):
return getSQLGrammar().parseString( sqlstring )

test( "SELECT * from XYZZY, ABC" )
test( "select * from SYS.XYZZY" )
test( "Select A from Sys.dual" )
...

-- Paul
 
F

Francis Avila

Paul McGuire wrote in message ...
One reason is to do late construction/initialization, or lazy
initialization. If an object is very time-consuming to construct, don't
create it at import time, wait until it is actually used. Once created,
save it in a global so that you don't have to re-create it every time.

Hmm, I hadn't thought of that. If this is a use case, aren't the
restrictions placed on global in the specs rather encumbering, and should be
removed? (Well, except for for-loop targets and formal parameters.) As it
is, to comply, you'd have to use a temporary name for construction, and then
assign to the global name.
 
P

Paul McGuire

Hmm, I hadn't thought of that. If this is a use case, aren't the
restrictions placed on global in the specs rather encumbering, and should be
removed? (Well, except for for-loop targets and formal parameters.) As it
is, to comply, you'd have to use a temporary name for construction, and then
assign to the global name.
¿Que?

What needs to be changed? See the example code that I posted. This is
exactly where "global" makes sense.

-- Paul
 
F

Francis Avila

Paul McGuire wrote in message ...
¿Que?

What needs to be changed? See the example code that I posted. This is
exactly where "global" makes sense.

I was thinking of e.g. an expensive class definition, but I didn't think
deeply enough. Never mind.
 

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

Forum statistics

Threads
474,173
Messages
2,570,937
Members
47,481
Latest member
ElviraDoug

Latest Threads

Top