tags:

views:

246

answers:

4

foo.py :

i = 10

def fi():
    global i
    i = 99

bar.py :

import foo
from foo import i

print i, foo.i
foo.fi()
print i, foo.i

This is problematic. Why does i not change when foo.i changes?

A: 

You could call a function instead of referencing a global variable.

RossFabricant
+8  A: 

What Ross is saying is to restucture foo like so:

_i = 10

def getI():
    return _i

def fi():
    global _i
    _i = 99

Then you will see it works the way you want:

>>> import foo
>>> print foo.getI()
10
>>> foo.fi()
>>> print foo.getI()
99

It is also 'better' in the sense that you avoid exporting a global, but still provide read access to it.

Shane C. Mason
+8  A: 

What import does in bar.py is set up an identifier called i in the bar.py module namespace that points to the same address as the identifier called i in the foo.py module namespace.

This is an important distinction... bar.i is not pointing to foo.i, but rather to the same space in memory where the object 10 is held that foo.i happens to point to at the same time. In python, the variable names are not the memory space... they are the identifier that points to a memory space. When you import in bar, you are setting up a local namespace identifier.

Your code behaves as expected until foo.fi() is called, when the identifier i in the foo.py namespace is changed to point to the literal 99, which is an object in memory obviously at a different place than 10. Now the module-level namespace dict for foo has i identifying a different object in memory than the identifier i in bar.py.

Shane and rossfabricant have good suggestions on how to adjust your modules to achieve what you want.

Jarret Hardie
+4  A: 

i inside foo.py is a different i from the one in bar.py. When in bar.py you do:

from foo import i

That creates a new i in bar.py that refers to the same object as the i in foo.py.

Your problem is: When you call foo.fi() and it does that:

i = 99

That assignment makes foo.py's i point to another integer object (99). Integer objects are immutable themselves (thankfully) so it only changes what foo.py's i is pointing to. Not bar.py's i. bar.py's i still points to the old object it was pointing before. (the integer immutable object 10)

You can test what I am talking about by placing the following command in bar.py:

print foo.i

it should print 99.

nosklo
Nice explanation.
Shane C. Mason