Python – Better Ways to Handle Static Variables

python

It seems that in Python, to declare a variable in a class, it is static (keeps its value in the next instances). What better way to get around this problem?

class Foo():
  number = 0
  def set(self):
    self.number = 1


>>> foo = Foo()
>>> foo.number
0
>>> foo.set()
>>> foo.number
1
>>> new_foo = Foo()
>>> new_foo.number
1

Best Answer

Variables defined at the class level are indeed "static", but I don't think they work quite the way you think they do. There are 2 levels here which you need to worry about. There are attributes at the class level, and there are attributes at the instance level. Whenever you do self.attribute = ... inside a method, you're setting an attribute at the instance level. Whenever python looks up an attribute, it first looks at the instance level, if it doesn't find the attribute, it looks at the class level.

This can be a little confusing (especially if the attribute is a reference to a mutable object). consider:

class Foo(object):
    attr = []  #class level attribute is Mutable
    def __init__(self):
        # in the next line, self.attr references the class level attribute since
        # there is no instance level attribute (yet)
        self.attr.append('Hello')
        self.attr = []
        # Now, we've created an instance level attribute, so further appends will
        # append to the instance level attribute, not the class level attribute.
        self.attr.append('World')

a = Foo()
print (a.attr)  #['World']
print (Foo.attr) #['Hello']
b = Foo()
print (b.attr)  #['World']
print (Foo.attr) #['Hello', 'Hello']

As others have mentioned, if you want an attribute to be specific to an instance, just initialize it as an instance attribute in __init__ (using self.attr = ...). __init__ is a special method which is run whenever a class is initialized (with a few exceptions that we won't discuss here).

e.g.

class Foo(object):
   def __init__(self):
       self.attr = 0
Related Question