[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

global/local variables

NIm

1/24/2008 11:37:00 PM

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?
8 Answers

Diez B. Roggisch

1/24/2008 11:49:00 PM

0

Tim Rau schrieb:
> 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

Steven D'Aprano

1/25/2008 12:09:00 AM

0

On Thu, 24 Jan 2008 15:37:09 -0800, Tim Rau wrote:

> 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.



--
Steven

NIm

1/25/2008 7:05:00 AM

0

On Jan 24, 7:09 pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> On Thu, 24 Jan 2008 15:37:09 -0800, Tim Rau wrote:
> > 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.
>
> --
> Steven

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.

Helmut Jarausch

1/25/2008 9:12:00 AM

0

Tim Rau wrote:

> 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

Steven D'Aprano

1/25/2008 10:32:00 AM

0

On Thu, 24 Jan 2008 23:04:42 -0800, Tim Rau wrote:

> 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.



--
Steven

NIm

1/25/2008 11:28:00 AM

0

On Jan 25, 5:31 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> On Thu, 24 Jan 2008 23:04:42 -0800, Tim Rau wrote:
> > 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.
>

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?

> > 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.
>
> --
> Steven

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.

Steven D'Aprano

1/25/2008 11:36:00 AM

0

On Fri, 25 Jan 2008 03:28:05 -0800, Tim Rau wrote:

>> 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?

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


--
Steven

NIm

1/25/2008 11:38:00 AM

0

On Jan 25, 5:31 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> On Thu, 24 Jan 2008 23:04:42 -0800, Tim Rau wrote:
> > 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.
>

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

**ENLIGHTENMENT**

\ /\ |
:o--- X |
/ \/ |

[snip]