Re: Problem with global variables

2008-08-09 Thread Nick Craig-Wood
Anthony Kuhlman [EMAIL PROTECTED] wrote:
  Pythoners,
  I'm having trouble understanding the behavior of global variables in a
  code I'm writing.  I have a file, test.py, with the following contents
 
  foo = []
 
  def goo():
  global foo
  foo = []
  foo.append(2)
 
  def moo():
  print foo
 
  In an ipython session, I see the following:
 
  In [1]: from test import *
 
  In [2]: foo
  Out[2]: []
 
  In [3]: goo()
 
  In [4]: foo
  Out[4]: []
 
  In [5]: moo()
  [2]
 
  I don't understand this behavior.  I assumed that foo as defined in
  test.py is a global object, but that doesn't seem to be the case.
  Obviously, there's some sort of namespace thing going on here that I
  don't get.  The ipython session seems to be dealing with one copy of foo
  while goo() and moo() are using an entirely different copy.  
 
  If I take out the line 'foo = []' in goo(), everything behaves exactly
  as I expect, that is, in ipython, when I type goo() followed by foo I
  get [2].
 
  Can anyone shed some light on this behavior?

The bit of information you need to solve this problem is that python
variables are not like variables in other languages, they don't
contain values, they refer to them.  This means that there can be many
names for the same value.

You've made two variables called foo, one in the interative
interpreter (by your from test import * statement) and one in the
test module, and by the time you get to [4] they have different
values.  The foo in the interpreter still refers to the original list,
but the foo in the test module has been overwritten with a new list by
the assignment 'foo = []'.  This didn't affect the foo in the
interactive interpreter.

Compare and contrast with this

 import test
 test.foo
[]
 test.goo()
 test.foo
[2]
 test.moo()
[2]

This works as you expect because you are always using the foo from the
test namespace.

My advice is to avoid global variables completely.  Consider wrapping
all your global variables into a class and exporting a single instance
of this class to keep your globals in.

Eg
--- test2.py ---
class Test(object):
def __init__(self):
self.foo = []
def goo(self):
self.foo.append(2)
def moo(self):
print self.foo

test = Test()


 from test2 import test
 test.foo
[]
 test.goo()
 test.foo
[2]
 test.moo()
[2]
   


-- 
Nick Craig-Wood [EMAIL PROTECTED] -- http://www.craig-wood.com/nick
--
http://mail.python.org/mailman/listinfo/python-list


Problem with global variables

2008-08-08 Thread Anthony Kuhlman
Pythoners,
I'm having trouble understanding the behavior of global variables in a
code I'm writing.  I have a file, test.py, with the following contents

foo = []

def goo():
global foo
foo = []
foo.append(2)

def moo():
print foo

In an ipython session, I see the following:

In [1]: from test import *

In [2]: foo
Out[2]: []

In [3]: goo()

In [4]: foo
Out[4]: []

In [5]: moo()
[2]

I don't understand this behavior.  I assumed that foo as defined in
test.py is a global object, but that doesn't seem to be the case.
Obviously, there's some sort of namespace thing going on here that I
don't get.  The ipython session seems to be dealing with one copy of foo
while goo() and moo() are using an entirely different copy.  

If I take out the line 'foo = []' in goo(), everything behaves exactly
as I expect, that is, in ipython, when I type goo() followed by foo I
get [2].

Can anyone shed some light on this behavior?

Cheers,
A.J.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2008-08-08 Thread Marc 'BlackJack' Rintsch
On Fri, 08 Aug 2008 13:10:48 -0400, Anthony Kuhlman wrote:

 I'm having trouble understanding the behavior of global variables in a
 code I'm writing.  I have a file, test.py, with the following contents
 
 foo = []
 
 def goo():
 global foo
 foo = []
 foo.append(2)
 
 def moo():
 print foo
 
 In an ipython session, I see the following:
 
 In [1]: from test import *
 
 In [2]: foo
 Out[2]: []
 
 In [3]: goo()
 
 In [4]: foo
 Out[4]: []
 
 In [5]: moo()
 [2]
 
 I don't understand this behavior.  I assumed that foo as defined in
 test.py is a global object, but that doesn't seem to be the case.

``global`` means module global.  There's no really global namespace in 
Python.

 The ipython session seems to be dealing with one copy of foo while
 goo() and moo() are using an entirely different copy.

The import binds the list from the module to the name `foo` in the 
IPython namespace.  When you call `goo()` it binds the name `foo` *within 
the module* to a new list.  This has of course no influence on the name 
in the IPython namespace which is still bound to the list object that was 
bound to `test.foo` before.

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Problem with global variables

2007-04-02 Thread Ed Jensen
I'm having a vexing problem with global variables in Python.  Please
consider the following Python code:

#! /usr/bin/env python

def tiny():
bar = []
for tmp in foo:
bar.append(tmp)
foo = bar

if __name__ == __main__:
foo = ['hello', 'world']
tiny()

When I try to run this, I get:

Traceback (most recent call last):
  File ./xtalk.py, line 11, in ?
tiny()
  File ./xtalk.py, line 5, in tiny
for tmp in foo:
UnboundLocalError: local variable 'foo' referenced before assignment

For some reason, Python can't see the global variable foo in the
function tiny().  Why is that?

If I change the code to this:

#! /usr/bin/env python

def tiny():
for tmp in foo:
print tmp

if __name__ == __main__:
foo = ['hello', 'world']
tiny()

I get this:

hello
world

All of a sudden, tiny() can see the global variable foo.  Very
confusing!  Why is it that tiny() sometimes can, and sometimes can't,
see the global variable foo?

If anyone can enlighten me about what's going on with Python and
global variables, I would appreciate it!
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread hg
Ed Jensen wrote:

 #! /usr/bin/env python
 
 def tiny():
 bar = []
 for tmp in foo:
 bar.append(tmp)
 foo = bar
 
 if __name__ == __main__:
 foo = ['hello', 'world']
 tiny()


Like this ?

#! /usr/bin/env python

def tiny():
    bar = []
gobal foo
    for tmp in foo:
        bar.append(tmp)
    foo = bar

if __name__ == __main__:
    foo = ['hello', 'world']
    tiny()


hg

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Laurent Pointal
Ed Jensen a écrit :
 I'm having a vexing problem with global variables in Python.  Please
 consider the following Python code:
 
 #! /usr/bin/env python
 
 def tiny():
 bar = []
 for tmp in foo:
 bar.append(tmp)
 foo = bar
 
 if __name__ == __main__:
 foo = ['hello', 'world']
 tiny()
 
 When I try to run this, I get:
 
 Traceback (most recent call last):
   File ./xtalk.py, line 11, in ?
 tiny()
   File ./xtalk.py, line 5, in tiny
 for tmp in foo:
 UnboundLocalError: local variable 'foo' referenced before assignment
 
 For some reason, Python can't see the global variable foo in the
 function tiny().  Why is that?
 
 If I change the code to this:
 
 #! /usr/bin/env python
 
 def tiny():
 for tmp in foo:
 print tmp
 
 if __name__ == __main__:
 foo = ['hello', 'world']
 tiny()
 
 I get this:
 
 hello
 world
 
 All of a sudden, tiny() can see the global variable foo.  Very
 confusing!  Why is it that tiny() sometimes can, and sometimes can't,
 see the global variable foo?
 
 If anyone can enlighten me about what's going on with Python and
 global variables, I would appreciate it!

To complete hg reply, Python compile your tiny function which contains a
foo assignment. As foo is not defined global, it is considered to be
local. So the error when you tries to iterate throught foo before
assigning it. And so the solution to add global foo before using it.

A+

Laurent.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Bjoern Schliessmann
Laurent Pointal wrote:

 And so the solution to add global foo before using it.

Didn't you read his final question?

| All of a sudden, tiny() can see the global variable foo.  Very
| confusing!  Why is it that tiny() sometimes can, and sometimes
| can't, see the global variable foo?

I have no explanation for this, but I'm interested in one, too.

Regards,


Björn

-- 
BOFH excuse #422:

Someone else stole your IP address, call the Internet detectives!

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Steve Holden
Bjoern Schliessmann wrote:
 Laurent Pointal wrote:
 
 And so the solution to add global foo before using it.
 
 Didn't you read his final question?
 
 | All of a sudden, tiny() can see the global variable foo.  Very
 | confusing!  Why is it that tiny() sometimes can, and sometimes
 | can't, see the global variable foo?
 
 I have no explanation for this, but I'm interested in one, too.
 
It doesn't happen all of a sudden, it happens when the assignment to 
foo is removed from the function definition. The interpreter therefore 
no longer regards foo as a local variable.

regards
  Steve
-- 
Steve Holden   +44 150 684 7255  +1 800 494 3119
Holden Web LLC/Ltd  http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
Recent Ramblings   http://holdenweb.blogspot.com

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Roel Schroeven
Bjoern Schliessmann schreef:
 Laurent Pointal wrote:
 
 And so the solution to add global foo before using it.
 
 Didn't you read his final question?
 
 | All of a sudden, tiny() can see the global variable foo.  Very
 | confusing!  Why is it that tiny() sometimes can, and sometimes
 | can't, see the global variable foo?
 
 I have no explanation for this, but I'm interested in one, too.

Within functions Python can read from global variables, even without a 
'global' statement. Complications only arise when you try to write to 
it: in that case Python assumes it is a local variable instead of a global.

It surprised me a bit when I first found out about this: I would have 
thought that Python would threat it as a local throughout the function 
until the function assigns something to it. That's not what happens: if 
the function assigns to it, *all* mentions of the variable are 
considered local.

-- 
If I have been able to see further, it was only because I stood
on the shoulders of giants.  -- Isaac Newton

Roel Schroeven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread irstas
On Apr 2, 5:29 pm, Bjoern Schliessmann usenet-
[EMAIL PROTECTED] wrote:
 Laurent Pointal wrote:
  And so the solution to add global foo before using it.

 Didn't you read his final question?

 | All of a sudden, tiny() can see the global variable foo.  Very
 | confusing!  Why is it that tiny() sometimes can, and sometimes
 | can't, see the global variable foo?

 I have no explanation for this, but I'm interested in one, too.

 Regards,

 Björn

Laurent Pointal did explain this. foo is considered to be a local
variable (scope limited to the function) if it's being assigned to in
a function and there's no global foo statement. So even the foo
before the actual assignment will refer to the local variable. But the
local variable hasn't been assigned yet at that point and an exception
is thrown. Yes, one could have a perfectly working function, then add
an innocent-looking assignment statement at the very end of the
function, and suddenly you'd get an exception thrown at the beginning
of the function where that variable is used - Far away from the place
where the modification was made.

Why does it work like this? Couldn't it be somehow more uniform or
less surprising?

Well, if one had to define global foo even when one were to just
read the variable foo, that'd be a pain in the ass. You'd have to use
global math to use math module in a function and global
anotherFunction to call anotherFunction, and so on. There's plenty of
stuff in the global scope that you don't normally assign to.

Another option would be to scrap global keyword and let foo = bar
do an assignment to the global variable if a global variable named
foo exists, but create (or assign) to a function local variable if
it doesn't exist. That'd work but programming would be horrible. Now
you'd have to know all the symbols that exist at the global scope,
because if you accidentally accessed a global variable instead of
local, your function would probably have undesirable side-effects.

Now, name clashes could be solved with a naming convention (which
could be enforced at the language level). It could be possible that
all accesses to global scope would have to be prefixed by some symbol
like $. E.g. $foo = 4; foo = 6 where former assigns to global foo,
latter to local foo. That's one option that might work and be somewhat
readable.. But not a good tradeoff IMO, considering how rarely global
assignment is needed and how often global variables are read.

A remaining option is to use different operator for assignment and
initialization. So you'd have to do e.g. a := 4; a = 7. I'm not sure
Pythonistas would prefer this either, although many other languages
choose this route (through lets or declarations typically).

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Ed Jensen
Ed Jensen [EMAIL PROTECTED] wrote:
 I'm having a vexing problem with global variables in Python.

SNIP

Thanks to everyone who replied.  The peculiar way Python handles
global variables in functions now makes sense to me.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Laurent Pointal
Bjoern Schliessmann wrote:

 Laurent Pointal wrote:
 
 And so the solution to add global foo before using it.
 
 Didn't you read his final question?

Yes, and i replies: which contains a foo assignment. As foo is not
defined global, it is considered to be local. 

Maybe my explanation was not clear enough with variable foo to be considered
local because there is an *assignment* to foo.

A+

Laurent.


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Problem with global variables

2007-04-02 Thread Bjoern Schliessmann
Laurent Pointal wrote:

 Yes, and i replies: which contains a foo assignment. As foo is
 not defined global, it is considered to be local.  
 
 Maybe my explanation was not clear enough with variable foo to be
 considered local because there is an *assignment* to foo.

Yep, thanks for the clarification. After four replies and despite
weird conjugations, I've definitely got it now ... ;)

Regards,


Björn

-- 
BOFH excuse #113:

Root nameservers are out of sync

-- 
http://mail.python.org/mailman/listinfo/python-list