Re: Problem with global variables
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
Re: Problem with global variables
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
Re: Problem with global variables
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
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
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
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
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
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
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
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
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