E.Beach
E.Beach

Reputation: 1857

Scope of Python Class Variable?

Are class variables essentially global variables?

Consider this example, in bar.py:

class Bar(object):
    b = {}

then in foo.py:

def foo1():
    import bar
    bar.Bar.b["key"] = "foo1"


def foo2():
    import bar
    print bar.Bar.b.get("key", "foo2")

foo1()
foo2()

The "key" value is persistently "foo1."

For my purposes this seems like a global variable. But why isn't the class variable being reset or deleted between the calls to foo1 and foo2?

Upvotes: 0

Views: 130

Answers (1)

mgilson
mgilson

Reputation: 309841

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.

Upvotes: 3

Related Questions