Home Static class variables in Python
Reply: 16

Static class variables in Python

Andrew Walker
Andrew Walker Published in 2008-09-16 01:46:36Z

Is it possible to have static class variables or methods in python? What syntax is required to do this?

Melebius Reply to 2017-06-06 13:00:27Z

Variables declared inside the class definition, but not inside a method are class or static variables:

>>> class MyClass:
...     i = 3
>>> MyClass.i

As @millerdev points out, this creates a class-level i variable, but this is distinct from any instance-level i variable, so you could have

>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)

This is different from C++ and Java, but not so different from C#, where a static member can't be accessed using a reference to an instance.

See what the Python tutorial has to say on the subject of classes and class objects.

@Steve Johnson has already answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.

class C:
    def f(arg1, arg2, ...): ...

@beidy recommends classmethods over staticmethod, as the method then receives the class type as the first argument, but I'm still a little fuzzy on the advantages of this approach over staticmethod. If you are too, then it probably doesn't matter.

emb Reply to 2008-09-16 23:29:49Z

Personally I would use a classmethod whenever I needed a static method. Mainly because I get the class as an argument.

class myObj(object):
   def myMethod(cls)
   myMethod = classmethod(myMethod) 

or use a decorator

class myObj(object):
   def myMethod(cls)

For static properties.. Its time you look up some python definition.. variable can always change. There are two types of them mutable and immutable.. Also, there are class attributes and instance attributes.. Nothing really like static attributes in the sense of java & c++

Why use static method in pythonic sense, if it has no relation whatever to the class! If I were you, I'd either use classmethod or define the method independent from the class.

Andrii Abramov
Andrii Abramov Reply to 2017-07-12 10:23:57Z

Static methods in python are called classmethods. Take a look at the following code

class MyClass:

    def myInstanceMethod(self):
        print 'output from an instance method'

    def myStaticMethod(cls):
        print 'output from a static method'

>>> MyClass.myInstanceMethod()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method myInstanceMethod() must be called [...]

>>> MyClass.myStaticMethod()
output from a static method

Notice that when we call the method myInstanceMethod, we get an error. This is because it requires that method be called on an instance of this class. The method myStaticMethod is set as a classmethod using the decorator @classmethod.

Just for kicks and giggles, we could call myInstanceMethod on the class by passing in an instance of the class, like so:

>>> MyClass.myInstanceMethod(MyClass())
output from an instance method
NITIN SRIVASTAV Reply to 2017-07-28 00:15:27Z

@Blair Conrad said static variables declared inside the class definition, but not inside a method are class or "static" variables:

>>> class Test(object):
...     i = 3
>>> Test.i

There are a few gotcha's here. Carrying on from the example above:

>>> t = Test()
>>> t.i     # static variable accessed via instance
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i  # we have not changed the static variable
>>> t.i     # we have overwritten Test.i on t by creating a new attribute t.i
>>> Test.i = 6 # to change the static variable we do it by assigning to the class
>>> t.i
>>> Test.i
>>> u = Test()
>>> u.i
6           # changes to t do not affect new instances of Test

# Namespaces are one honking great idea -- let's do more of those!
>>> Test.__dict__
{'i': 6, ...}
>>> t.__dict__
{'i': 5}
>>> u.__dict__

Notice how the instance variable t.i got out of sync with the "static" class variable when the attribute i was set directly on t. This is because i was re-bound within the t namespace, which is distinct from the Test namespace. If you want to change the value of a "static" variable, you must change it within the scope (or object) where it was originally defined. I put "static" in quotes because Python does not really have static variables in the sense that C++ and Java do.

Although it doesn't say anything specific about static variables or methods, the Python tutorial has some relevant information on classes and class objects.

@Steve Johnson also answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.

class Test(object):
    def f(arg1, arg2, ...):

@beid also mentioned classmethod, which is similar to staticmethod. A classmethod's first argument is the class object. Example:

class Test(object):
    i = 3 # class (or static) variable
    def g(cls, arg):
        # here we can use 'cls' instead of the class name (Test)
        if arg > cls.i:
            cls.i = arg # would the the same as  Test.i = arg1

Ross Reply to 2008-09-17 04:01:08Z

To avoid any potential confusion, I would like to contrast static variables and immutable objects.

Some primitive object types like integers, floats, strings, and touples are immutable in Python. This means that the object that is referred to by a given name cannot change if it is of one of the aforementioned object types. The name can be reassigned to a different object, but the object itself may not be changed.

Making a variable static takes this a step further by disallowing the variable name to point to any object but that to which it currently points. (Note: this is a general software concept and not specific to Python; please see others' posts for information about implementing statics in Python).

Ned Batchelder
Ned Batchelder Reply to 2014-08-24 17:43:30Z

You can also add class variables to classes on the fly

>>> class X:
...     pass
>>> X.bar = 0
>>> x = X()
>>> x.bar
>>> x.foo
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
>>> X.foo = 1
>>> x.foo

And class instances can change class variables

class X:
  l = []
  def __init__(self):

print X().l
print X().l

>python test.py
[1, 1]
Bartosz Ptaszynski
Bartosz Ptaszynski Reply to 2011-11-20 12:06:23Z

You could also enforce a class to be static using metaclass.

class StaticClassError(Exception):

class StaticClass:
    __metaclass__ = abc.ABCMeta

    def __new__(cls, *args, **kw):
        raise StaticClassError("%s is a static class and cannot be initiated."
                                % cls)

class MyClass(StaticClass):
    a = 1
    b = 3

    def add(x, y):
        return x+y

Then whenever by accident you try to initialize MyClass you'll get an StaticClassError.

jondinham Reply to 2012-03-08 06:06:05Z

One special thing to note about static properties & instance properties, shown in the example below:

class my_cls:
  my_prop = 0

#static property
print my_cls.my_prop  #--> 0

#assign value to static property
my_cls.my_prop = 1 
print my_cls.my_prop  #--> 1

#access static property thru' instance
my_inst = my_cls()
print my_inst.my_prop #--> 1

#instance property is different from static property 
#after being assigned a value
my_inst.my_prop = 2
print my_cls.my_prop  #--> 1
print my_inst.my_prop #--> 2

This means before assigning the value to instance property, if we try to access the property thru' instance, the static value is used. Each property declared in python class always has a static slot in memory.

Kevin Guan
Kevin Guan Reply to 2016-04-19 23:42:58Z

The best way I found is to use another class. You can create an object and then use it on other objects.

class staticFlag:
    def __init__(self):
        self.__success = False
    def isSuccess(self):
        return self.__success
    def succeed(self):
        self.__success = True

class tryIt:
    def __init__(self, staticFlag):
        self.isSuccess = staticFlag.isSuccess
        self.succeed = staticFlag.succeed

tryArr = []
flag = staticFlag()
for i in range(10):
    if i == 5:
    print tryArr[i].isSuccess()

With the example above, I made a class named staticFlag.

This class should present the static var __success (Private Static Var).

tryIt class represented the regular class we need to use.

Now I made an object for one flag (staticFlag). This flag will be sent as reference to all the regular objects.

All these objects are being added to the list tryArr.

This Script Results:

Markus Reply to 2016-08-03 11:37:36Z

When define some member variable outside any member method, the variable can be either static or non-static depending on how the variable is expressed.

  • CLASSNAME.var is static variable
  • INSTANCENAME.var is not static variable.
  • self.var inside class is not static variable.
  • var inside the class member function is not defined.

For example:


class A:

    def printvar(self):
        print "self.var is %d" % self.var
        print "A.var is %d" % A.var

    a = A()
    a.var = 2

    A.var = 3

The results are

self.var is 2
A.var is 1
self.var is 2
A.var is 3
Community Reply to 2017-05-23 12:18:14Z

In regards to this answer, for a constant static variable, you can use a descriptor. Here's an example:

class ConstantAttribute(object):
    '''You can initialize my value but not change it.'''
    def __init__(self, value):
        self.value = value

    def __get__(self, obj, type=None):
        return self.value

    def __set__(self, obj, val):

class Demo(object):
    x = ConstantAttribute(10)

class SubDemo(Demo):
    x = 10

demo = Demo()
subdemo = SubDemo()
# should not change
demo.x = 100
# should change
subdemo.x = 100
print "small demo", demo.x
print "small subdemo", subdemo.x
print "big demo", Demo.x
print "big subdemo", SubDemo.x

resulting in ...

small demo 10
small subdemo 100
big demo 10
big subdemo 10

You can always raise an exception if quietly ignoring setting value (pass above) is not your thing. If you're looking for a C++, Java style static class variable:

class StaticAttribute(object):
    def __init__(self, value):
        self.value = value

    def __get__(self, obj, type=None):
        return self.value

    def __set__(self, obj, val):
        self.value = val

Have a look at this answer and the official docs HOWTO for more information about descriptors.

Rick Teachey
Rick Teachey Reply to 2017-12-08 16:12:57Z

Static and Class Methods

As the other answers have noted, static and class methods are easily accomplished using the built-in decorators:

class Test(object):

    # regular instance method:
    def MyMethod(self):

    # class method:
    def MyClassMethod(klass):

    # static method:
    def MyStaticMethod():

As usual, the first argument to MyMethod() is bound to the class instance object. In contrast, the first argument to MyClassMethod() is bound to the class object itself (e.g., in this case, Test). For MyStaticMethod(), none of the arguments are bound, and having arguments at all is optional.

"Static Variables"

However, implementing "static variables" (well, mutable static variables, anyway, if that's not a contradiction in terms...) is not as straight forward. As millerdev pointed out in his answer, the problem is that Python's class attributes are not truly "static variables". Consider:

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i

This is because the line x.i = 12 has added a new instance attribute i to x instead of changing the value of the Test class i attribute.

Partial expected static variable behavior, i.e., syncing of the attribute between multiple instances (but not with the class itself; see "gotcha" below), can be achieved by turning the class attribute into a property:

class Test(object):

    _i = 3

    def i(self):
        return type(self)._i

    def i(self,val):
        type(self)._i = val

## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)

Now you can do:

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced

The static variable will now remain in sync between all class instances.

(NOTE: That is, unless a class instance decides to define its own version of _i! But if someone decides to do THAT, they deserve what they get, don't they???)

Note that technically speaking, i is still not a 'static variable' at all; it is a property, which is a special type of descriptor. However, the property behavior is now equivalent to a (mutable) static variable synced across all class instances.

Immutable "Static Variables"

For immutable static variable behavior, simply omit the property setter:

class Test(object):

    _i = 3

    def i(self):
        return type(self)._i

## (except with separate methods for getting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    i = property(get_i)

Now attempting to set the instance i attribute will return an AttributeError:

x = Test()
assert x.i == 3  # success
x.i = 12         # ERROR

One Gotcha to be Aware of

Note that the above methods only work with instances of your class - they will not work when using the class itself. So for example:

x = Test()
assert x.i == Test.i  # ERROR

# x.i and Test.i are two different objects:
type(Test.i)  # class 'property'
type(x.i)     # class 'int'

The line assert Test.i == x.i produces an error, because the i attribute of Test and x are two different objects.

Many people will find this surprising. However, it should not be. If we go back and inspect our Test class definition (the second version), we take note of this line:

    i = property(get_i) 

Clearly, the member i of Test must be a property object, which is the type of object returned from the property function.

If you find the above confusing, you are most likely still thinking about it from the perspective of other languages (e.g. Java or c++). You should go study the property object, about the order in which Python attributes are returned, the descriptor protocol, and the method resolution order (MRO).

I present a solution to the above 'gotcha' below; however I would suggest - strenuously - that you do not try to do something like the following until - at minimum - you thoroughly understand why assert Test.i = x.i causes an error.

REAL, ACTUAL Static Variables - Test.i == x.i

I present the (Python 3) solution below for informational purposes only. I am not endorsing it as a "good solution". I have my doubts as to whether emulating the static variable behavior of other languages in Python is ever actually necessary. However, regardless as to whether it is actually useful, the below should help further understanding of how Python works.

UPDATE: this attempt is really pretty awful; if you insist on doing something like this (hint: please don't; Python is a very elegant language and shoe-horning it into behaving like another language is just not necessary), use the code in Ethan Furman's answer instead.

Emulating static variable behavior of other languages using a metaclass

A metaclass is the class of a class. The default metaclass for all classes in Python (i.e., the "new style" classes post Python 2.3 I believe) is type. For example:

type(int)  # class 'type'
type(str)  # class 'type'
class Test(): pass
type(Test) # class 'type'

However, you can define your own metaclass like this:

class MyMeta(type): pass

And apply it to your own class like this (Python 3 only):

class MyClass(metaclass = MyMeta):

type(MyClass)  # class MyMeta

Below is a metaclass I have created which attempts to emulate "static variable" behavior of other languages. It basically works by replacing the default getter, setter, and deleter with versions which check to see if the attribute being requested is a "static variable".

A catalog of the "static variables" is stored in the StaticVarMeta.statics attribute. All attribute requests are initially attempted to be resolved using a substitute resolution order. I have dubbed this the "static resolution order", or "SRO". This is done by looking for the requested attribute in the set of "static variables" for a given class (or its parent classes). If the attribute does not appear in the "SRO", the class will fall back on the default attribute get/set/delete behavior (i.e., "MRO").

from functools import wraps

class StaticVarsMeta(type):
    '''A metaclass for creating classes that emulate the "static variable" behavior
    of other languages. I do not advise actually using this for anything!!!

    Behavior is intended to be similar to classes that use __slots__. However, "normal"
    attributes and __statics___ can coexist (unlike with __slots__). 

    Example usage: 

        class MyBaseClass(metaclass = StaticVarsMeta):
            __statics__ = {'a','b','c'}
            i = 0  # regular attribute
            a = 1  # static var defined (optional)

        class MyParentClass(MyBaseClass):
            __statics__ = {'d','e','f'}
            j = 2              # regular attribute
            d, e, f = 3, 4, 5  # Static vars
            a, b, c = 6, 7, 8  # Static vars (inherited from MyBaseClass, defined/re-defined here)

        class MyChildClass(MyParentClass):
            __statics__ = {'a','b','c'}
            j = 2  # regular attribute (redefines j from MyParentClass)
            d, e, f = 9, 10, 11   # Static vars (inherited from MyParentClass, redefined here)
            a, b, c = 12, 13, 14  # Static vars (overriding previous definition in MyParentClass here)'''
    statics = {}
    def __new__(mcls, name, bases, namespace):
        # Get the class object
        cls = super().__new__(mcls, name, bases, namespace)
        # Establish the "statics resolution order"
        cls.__sro__ = tuple(c for c in cls.__mro__ if isinstance(c,mcls))

        # Replace class getter, setter, and deleter for instance attributes
        cls.__getattribute__ = StaticVarsMeta.__inst_getattribute__(cls, cls.__getattribute__)
        cls.__setattr__ = StaticVarsMeta.__inst_setattr__(cls, cls.__setattr__)
        cls.__delattr__ = StaticVarsMeta.__inst_delattr__(cls, cls.__delattr__)
        # Store the list of static variables for the class object
        # This list is permanent and cannot be changed, similar to __slots__
            mcls.statics[cls] = getattr(cls,'__statics__')
        except AttributeError:
            mcls.statics[cls] = namespace['__statics__'] = set() # No static vars provided
        # Check and make sure the statics var names are strings
        if any(not isinstance(static,str) for static in mcls.statics[cls]):
            typ = dict(zip((not isinstance(static,str) for static in mcls.statics[cls]), map(type,mcls.statics[cls])))[True].__name__
            raise TypeError('__statics__ items must be strings, not {0}'.format(typ))
        # Move any previously existing, not overridden statics to the static var parent class(es)
        if len(cls.__sro__) > 1:
            for attr,value in namespace.items():
                if attr not in StaticVarsMeta.statics[cls] and attr != ['__statics__']:
                    for c in cls.__sro__[1:]:
                        if attr in StaticVarsMeta.statics[c]:
        return cls
    def __inst_getattribute__(self, orig_getattribute):
        '''Replaces the class __getattribute__'''
        def wrapper(self, attr):
            if StaticVarsMeta.is_static(type(self),attr):
                return StaticVarsMeta.__getstatic__(type(self),attr)
                return orig_getattribute(self, attr)
        return wrapper
    def __inst_setattr__(self, orig_setattribute):
        '''Replaces the class __setattr__'''
        def wrapper(self, attr, value):
            if StaticVarsMeta.is_static(type(self),attr):
                StaticVarsMeta.__setstatic__(type(self),attr, value)
                orig_setattribute(self, attr, value)
        return wrapper
    def __inst_delattr__(self, orig_delattribute):
        '''Replaces the class __delattr__'''
        def wrapper(self, attr):
            if StaticVarsMeta.is_static(type(self),attr):
                orig_delattribute(self, attr)
        return wrapper
    def __getstatic__(cls,attr):
        '''Static variable getter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
                    return getattr(c,attr)
                except AttributeError:
        raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
    def __setstatic__(cls,attr,value):
        '''Static variable setter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
    def __delstatic__(cls,attr):
        '''Static variable deleter'''
        for c in cls.__sro__:
            if attr in StaticVarsMeta.statics[c]:
                except AttributeError:
        raise AttributeError(cls.__name__ + " object has no attribute '{0}'".format(attr))
    def __delattr__(cls,attr):
        '''Prevent __sro__ attribute from deletion'''
        if attr == '__sro__':
            raise AttributeError('readonly attribute')
    def is_static(cls,attr):
        '''Returns True if an attribute is a static variable of any class in the __sro__'''
        if any(attr in StaticVarsMeta.statics[c] for c in cls.__sro__):
            return True
        return False
Ethan Furman
Ethan Furman Reply to 2016-03-25 09:02:25Z

It is possible to have static class variables, but probably not worth the effort.

Here's a proof-of-concept written in Python 3 -- if any of the exact details are wrong the code can be tweaked to match just about whatever you mean by a static variable:

class Static:
    def __init__(self, value, doc=None):
        self.deleted = False
        self.value = value
        self.__doc__ = doc
    def __get__(self, inst, cls=None):
        if self.deleted:
            raise AttributeError('Attribute not set')
        return self.value
    def __set__(self, inst, value):
        self.deleted = False
        self.value = value
    def __delete__(self, inst):
        self.deleted = True

class StaticType(type):
    def __delattr__(cls, name):
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            super(StaticType, cls).__delattr__(name)
    def __getattribute__(cls, *args):
        obj = super(StaticType, cls).__getattribute__(*args)
        if isinstance(obj, Static):
            obj = obj.__get__(cls, cls.__class__)
        return obj
    def __setattr__(cls, name, val):
        # check if object already exists
        obj = cls.__dict__.get(name)
        if isinstance(obj, Static):
            obj.__set__(name, val)
            super(StaticType, cls).__setattr__(name, val)

and in use:

class MyStatic(metaclass=StaticType):
    Testing static vars
    a = Static(9)
    b = Static(12)
    c = 3

class YourStatic(MyStatic):
    d = Static('woo hoo')
    e = Static('doo wop')

and some tests:

ms1 = MyStatic()
ms2 = MyStatic()
ms3 = MyStatic()
assert ms1.a == ms2.a == ms3.a == MyStatic.a
assert ms1.b == ms2.b == ms3.b == MyStatic.b
assert ms1.c == ms2.c == ms3.c == MyStatic.c
ms1.a = 77
assert ms1.a == ms2.a == ms3.a == MyStatic.a
ms2.b = 99
assert ms1.b == ms2.b == ms3.b == MyStatic.b
MyStatic.a = 101
assert ms1.a == ms2.a == ms3.a == MyStatic.a
MyStatic.b = 139
assert ms1.b == ms2.b == ms3.b == MyStatic.b
del MyStatic.b
for inst in (ms1, ms2, ms3):
        getattr(inst, 'b')
    except AttributeError:
        print('AttributeError not raised on %r' % attr)
ms1.c = 13
ms2.c = 17
ms3.c = 19
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19
MyStatic.c = 43
assert ms1.c == 13
assert ms2.c == 17
assert ms3.c == 19

ys1 = YourStatic()
ys2 = YourStatic()
ys3 = YourStatic()
MyStatic.b = 'burgler'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
assert ys1.d == ys2.d == ys3.d == YourStatic.d
assert ys1.e == ys2.e == ys3.e == YourStatic.e
ys1.a = 'blah'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
ys2.b = 'kelp'
assert ys1.b == ys2.b == ys3.b == YourStatic.b == MyStatic.b
ys1.d = 'fee'
assert ys1.d == ys2.d == ys3.d == YourStatic.d
ys2.e = 'fie'
assert ys1.e == ys2.e == ys3.e == YourStatic.e
MyStatic.a = 'aargh'
assert ys1.a == ys2.a == ys3.a == YourStatic.a == MyStatic.a
jmunsch Reply to 2017-01-01 02:56:08Z

Static Variables in Class factory python3.6

For anyone using a class factory with python3.6 and up use the nonlocal keyword to add it to the scope / context of the class being created like so:

>>> def SomeFactory(some_var=None):
...     class SomeClass(object):
...         nonlocal some_var
...         def print():
...             print(some_var)
...     return SomeClass
>>> SomeFactory(some_var="hello world").print()
hello world
Mari Selvan
Mari Selvan Reply to 2017-02-22 13:01:13Z

Absolutely Yes, Python by itself don't have any static data member explicitly, but We can have by doing so

class A:
    counter =0
    def callme (self):
        A.counter +=1
    def getcount (self):
        return self.counter  
>>> x=A()
>>> y=A()
>>> print(x.getcount())
>>> print(y.getcount())
>>> x.callme() 
>>> print(x.getcount())
>>> print(y.getcount())




here object (x) alone increment the counter variable
from 0 to 1 by not object y. But result it as "static counter"
Sanju Reply to 2017-12-17 17:19:31Z

One very interesting point about Python's attribute lookup is that it can be used to create "virtual variables":

class A(object):


  def __init__(self,d): 

  def say(self): 
      print("%s %s!"%(self.label,self.data))

class B(A):
  label="Bold"  # overrides A.label

A(5).say()      # Amazing 5!
B(3).say()      # Bold 3!

Normally there aren't any assignments to these after they are created. Note that the lookup uses self because, although label is static in the sense of not being associated with a particular instance, the value still depends on the (class of the) instance.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.442243 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO