global/local variables

T

Tim Rau

What makes python decide whether a particular variable is global or
local? I've got a list and a integer, both defined at top level, no
indentation, right next to each other:

allThings = []
nextID = 0

and yet, in the middle of a function, python sees one and doesn't see
the other:

class ship(thing):
###snip###
def step(self):
###snip###
if keys[K_up]
for n in range(0,2): #sparks/newton second is
proportional to framerate
divergence = 5.0
p = self.body.getRelPointPos((-0.15,0,0))
v = self.body.vectorToWorld((-100+ random.uniform(-
divergence,divergence) ,random.uniform(-divergence,divergence),0))
allThings.append(particle(p,v))
allThings[len(allThings)-1].id = nextID
nextID += 1


I don't think it's important, but the function is defined before the
two globals. What gives?
 
D

Diez B. Roggisch

Tim said:
What makes python decide whether a particular variable is global or
local? I've got a list and a integer, both defined at top level, no
indentation, right next to each other:

allThings = []
nextID = 0

and yet, in the middle of a function, python sees one and doesn't see
the other:

class ship(thing):
###snip###
def step(self):
###snip###
if keys[K_up]
for n in range(0,2): #sparks/newton second is
proportional to framerate
divergence = 5.0
p = self.body.getRelPointPos((-0.15,0,0))
v = self.body.vectorToWorld((-100+ random.uniform(-
divergence,divergence) ,random.uniform(-divergence,divergence),0))
allThings.append(particle(p,v))
allThings[len(allThings)-1].id = nextID
nextID += 1


I don't think it's important, but the function is defined before the
two globals. What gives?

The difference is that you assign to nextID in your function. Statements
of the form


foo = expression

will make foo a function-local variable.

If you want it to be a module-global, you need to do

global foo

foo = expression

If you do this:


bar = 10

def f():
print bar

you don't assign to a variable, but only read. So if it's not found
locally, it will be looked up globally.

Diez
 
S

Steven D'Aprano

What makes python decide whether a particular variable
is global or local?

For starters, if the line of code is not inside a class or function, that
is, it's at the top level of a module, it is global.

More interesting is if it is inside a function or class. If you assign to
the name in the function, Python assumes it is local *unless* you have
defined it as global with the global statement.

Otherwise, Python will treat it as global.

I've got a list and a integer, both defined at top level, no
indentation, right next to each other:

allThings = []
nextID = 0

and yet, in the middle of a function, python sees one and doesn't see
the other:

I've tried to run your code -- and it isn't easy, involving much
backwards-and-forwards copying and pasting, thanks to word-wrap in you
post -- and the error I get is:

SyntaxError: invalid syntax

because you left off the colon from the first if statement.

I'm not especially inclined to start hunting through your code fixing any
other errors in order to find the error you think you're getting. How
about if you quote the exception traceback you actually get?

I don't think it's important, but the function is defined before
the two globals.

Nope, not important. What's important is whether the function is *called*
before or after the globals are created.

If you're using global variables in your code, you probably should stop.
As a general rule, global variables are poor programming practice for a
number of reasons. Google on "Global variables considered harmful" for
some examples.
 
T

Tim Rau

What makes python decide whether a particular variable
is global or local?

For starters, if the line of code is not inside a class or function, that
is, it's at the top level of a module, it is global.

More interesting is if it is inside a function or class. If you assign to
the name in the function, Python assumes it is local *unless* you have
defined it as global with the global statement.

Otherwise, Python will treat it as global.
I've got a list and a integer, both defined at top level, no
indentation, right next to each other:
allThings = []
nextID = 0
and yet, in the middle of a function, python sees one and doesn't see
the other:

I've tried to run your code -- and it isn't easy, involving much
backwards-and-forwards copying and pasting, thanks to word-wrap in you
post -- and the error I get is:

SyntaxError: invalid syntax

because you left off the colon from the first if statement.

I'm not especially inclined to start hunting through your code fixing any
other errors in order to find the error you think you're getting. How
about if you quote the exception traceback you actually get?
I don't think it's important, but the function is defined before
the two globals.

Nope, not important. What's important is whether the function is *called*
before or after the globals are created.
That's been my experience so far.
If you're using global variables in your code, you probably should stop.
As a general rule, global variables are poor programming practice for a
number of reasons. Google on "Global variables considered harmful" for
some examples.

I'm sorry: I forgot to say what my problem was. Python seems to think
that nextID is a local, and complains that it can't find it. THis is
not the full text of the function, just the level that is causing
errors. the lack of : on the if is a transcription error.
Traceback (most recent call last):
File "C:\Documents and Settings\Owner\My Documents\NIm's code\sandbox
\sandbox.py", line 248, in <module>
thing.step()
File "C:\Documents and Settings\Owner\My Documents\NIm's code\sandbox
\sandbox.py", line 112, in step
allThings[len(allThings)-1].id = nextID
UnboundLocalError: local variable 'nextID' referenced before
assignment

I want to know why it says 'local variable' it never had a problem
when just allThings was in there.

as for the objection to global variable: If I didn't make them global,
I'd make them part of a singleton class called gameVars that would get
passed everywhere. It's unlikely that they'll get mixed in with
anyhting else, as they fulfill a unique function. Also, I think it's
more convenient, and I am, after all, my own employer when it comes to
programming.
 
H

Helmut Jarausch

Tim said:
I'm sorry: I forgot to say what my problem was. Python seems to think
that nextID is a local, and complains that it can't find it. THis is
not the full text of the function, just the level that is causing
errors. the lack of : on the if is a transcription error.
Traceback (most recent call last):
File "C:\Documents and Settings\Owner\My Documents\NIm's code\sandbox
\sandbox.py", line 248, in <module>
thing.step()
File "C:\Documents and Settings\Owner\My Documents\NIm's code\sandbox
\sandbox.py", line 112, in step
allThings[len(allThings)-1].id = nextID
UnboundLocalError: local variable 'nextID' referenced before
assignment

But in the next line in the same function you say
nextID+= 1

Since there is an assignment to nextID in the same function without
a global statement, you tell Python, that nextID is a local variable.

Note: Assignment (anywhere in a function) is a local definition unless
there is a global statement in this function
I want to know why it says 'local variable' it never had a problem
when just allThings was in there.

as for the objection to global variable: If I didn't make them global,
I'd make them part of a singleton class called gameVars that would get
passed everywhere. It's unlikely that they'll get mixed in with
anyhting else, as they fulfill a unique function. Also, I think it's
more convenient, and I am, after all, my own employer when it comes to
programming.


--
Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany
 
S

Steven D'Aprano

UnboundLocalError: local variable 'nextID' referenced before assignment

When you assign to a name in Python, the compiler treats it as a local
variable. So when you have a line like this:

nextID += 1 # equivalent to nextID = nextID + 1

you are getting the value of the _local_ nextID before you have assigned
a value to it.
I want to know why it says 'local variable' it never had a problem when
just allThings was in there.

Because you don't assign to allThings, and therefore it is treated as
global.

as for the objection to global variable: If I didn't make them global,
I'd make them part of a singleton class called gameVars that would get
passed everywhere.

*shrug* Or you could consider a different program structure completely.
It's unlikely that they'll get mixed in with anyhting
else, as they fulfill a unique function. Also, I think it's more
convenient, and I am, after all, my own employer when it comes to
programming.

Hey, it's your time and effort. If you want to, you can download the
Python "goto" module, and use goto and comefrom in your code.

No, that's unfair. Globals aren't as harmful as goto. I'm not saying that
globals are verboten or that they have no place in 21st century
programming at all. Since I know nothing about your program, I can't
judge whether globals are the right way to go or not. But I am saying
that as a general rule, reliance on global variables often leads to
fragile code with hard-to-diagnose bugs. Your mileage may vary.
 
T

Tim Rau

When you assign to a name in Python, the compiler treats it as a local
variable. So when you have a line like this:

nextID += 1 # equivalent to nextID = nextID + 1

you are getting the value of the _local_ nextID before you have assigned
a value to it.


Because you don't assign to allThings, and therefore it is treated as
global.

Hmm.... so I can't assign to globals in a local environment? How do I
make it see that I'm assigning to a global?
*shrug* Or you could consider a different program structure completely.


Hey, it's your time and effort. If you want to, you can download the
Python "goto" module, and use goto and comefrom in your code.

No, that's unfair. Globals aren't as harmful as goto. I'm not saying that
globals are verboten or that they have no place in 21st century
programming at all. Since I know nothing about your program, I can't
judge whether globals are the right way to go or not. But I am saying
that as a general rule, reliance on global variables often leads to
fragile code with hard-to-diagnose bugs. Your mileage may vary.

Ha! Gotos I understand the evil of. Human beings don't think that way.
Humans are not put together in terms of gotos. Human language does not
normally contain gotos. Global, however, seem useful to me. It seems
like there are a few things which EVERYONE should know. When you find
something often used from a variety of different places, everyone
should know about it. It saves time from developing lengthy argument
passing chains to follow the passing chains of your program. It keeps
the number of arguments low, and easily remembered. This may be more
important in python, because python has no type, and where you would
have had a type error for forgetting which arg goes where, you have
some random thing.

Also, My programming style tends towards a mongrel of functional and
object oriented programming. I tend to use lone functions when they
have no internal state, and objects when they have internal state, but
it's not ironclad. It's just what makes sense to me at the time. I'm
not defending myself, I'm just setting out my point of view. I'd like
to see what you think of it.
 
S

Steven D'Aprano

Hmm.... so I can't assign to globals in a local environment? How do I
make it see that I'm assigning to a global?

I thought somebody had already mentioned this... possibly even me...

You can declare a name as global by using the global statement:

def foo():
global x
x += 1
 
T

Tim Rau

When you assign to a name in Python, the compiler treats it as a local
variable. So when you have a line like this:

nextID += 1 # equivalent to nextID = nextID + 1

you are getting the value of the _local_ nextID before you have assigned
a value to it.


Because you don't assign to allThings, and therefore it is treated as
global.


*shrug* Or you could consider a different program structure completely.

Oh, wait nevermind, I now understand what global nextID is for

**ENLIGHTENMENT**

\ /\ |
:eek:--- X |
/ \/ |

[snip]
 

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top