It's a class attribute. In your case, the dict is bound to the class Bar. Everytime you import bar, you get the same class bar.Bar (after all, it is in the bar's global namespace), and consequentially, you get the same dict bar.Bar.b.
If you want each Bar instance to have a different dict, you need to make an instance:
class Bar(object):
def __init__(self):
self.b = {}
And then:
def foo1():
import bar
bar.Bar().b["key"] = "foo1"
def foo2():
import bar
print bar.Bar().b.get("key", "foo2")
foo1()
foo2()
As far as why the module bar isn't being garbage collected, when you import something, python stores a reference to that module (see sys.modules). The next time you import that module, python picks out the proper item from sys.modules and gives you a reference to it. There are a few reasons for this.
- Efficiency -- Why re-evaluate code you've already evaluated?
- Sane behavior
Imagine a module with a special value:
# mod.py
CONSTANT = object()
now you want to use that in foo.py and bar.py.
# bar.py
import mod
def bar():
return mod.CONSTANT
# foo.py
import mod
import bar
if bar.bar() is mod.CONSTANT:
do_something()
If the import wasn't cached, then mod.CONSTANT could be different in foo and in bar which would be very surprising.