Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't globals work as I would expect when importing?

In the file foo.py I have this:

d = {}
d['x'] = 0
x = 0

def foo():
    global d
    global x
    d['x'] = 1
    x = 1

Then in an interpreter:

>>> from foo import *
>>> d['x']
0
>>> x
0
>>> foo()
>>> d['x']
1
>>> x
0

I expected this:

>>> x
1

What am I not understanding?

like image 810
Daniel Avatar asked Nov 25 '13 23:11

Daniel


2 Answers

The global namespace of foo is imported into your current namespace only once (when you do the from foo import *). After that, if you change foo's namespace, it won't be reflected in your current namespace.

Note that you can still change objects in foo's namespace and see the changed in your current namespace. That is why you see changes in d. You still have a reference to the same object d that lives in foo's namespace.

But, when you set:

x = 1

This rebinds a new object in the namespace of foo.

like image 114
mgilson Avatar answered Oct 31 '22 00:10

mgilson


Your foo module and the main module that imports it (named __main__) have separate namespaces.

Here's what happens:

  1. Importing foo sets foo's global variable x to refer to the integer object 0.
  2. This reference is copied into __main__ as the global variable x.
  3. You call foo.foo(), which sets foo's global variable x to refer to the integer object 1.
  4. You print __main__'s global variable x. Because you never changed what this x refers to, it still refers to 0, which is what is printed.

In short, importing a name into a module does not create any kind of binding between the names in the two modules. They initially refer to the same value, but if one name is re-bound to a different object, the other does not necessarily follow.

This is (one) reason why import foo is generally a better idea. Referring to foo.x explicitly in __main__ refers exactly to foo's global variable x, and will refer to the name's current value even if it has been changed.

like image 26
kindall Avatar answered Oct 30 '22 23:10

kindall