1

I need a way to create a static class variable in Python that only the class will have. I can't afford this variable to be created over and over again for each instance, because the target class variable will be a huge read-only data structure. Each instance must be able to access it for read-only purposes throught the class, but since it's a giant bulk of data and there will be thousands instances, I can't afford that each instance will create another copy of this data structure again.

I found this question, but it doesn't solve my problem, because the static class variable suggested is created for each instance:

>>> class MyClass():
    i = 1
>>> m = MyClass()
>>> m.i
1

In other words, I'm looking for a static class variable like in PHP:

<?php
class Foo
{
    public static $my_static = 'foo';
}

$foo = new Foo();
print $foo::$my_static . "\n";     // Accessable throught the class
print $foo->my_static . "\n";      // Undefined "Property" my_static     
?>

This is exactly what I need, the static class variable is created only once for the class, all instances can access it throught the class but this static class variable isn't created over and over for each new instance. Is it possible to create a static class variable like this in Python?

PS: I now there are some workarounds if I don't use OOP, but if I could find a good and clearly readable OOP solution it would make more sense in the project as a whole.

11
  • 3
    Why do you think that just because you can access it as m.i it's actually getting created multiple times? Commented May 12, 2015 at 22:15
  • "the static class variable suggested is created for each instance" - no, that's not correct. Commented May 12, 2015 at 22:15
  • That you can acces it from an instance does not mean it is created for each instance. Commented May 12, 2015 at 22:15
  • 1
    @renatov if you assign m.i on an instance, at that point it creates a new one, shadowing the class var. Commented May 12, 2015 at 22:17
  • 1
    @renatov yup, exactly. Commented May 12, 2015 at 22:19

2 Answers 2

4

the static class variable suggested is created for each instance

That is false, as you can easily demonstrate:

>>> class Test():
    class_attr = []


>>> t1 = Test()
>>> t2 = Test()
>>> t1.class_attr is t2.class_attr
True  # this means that they reference exactly the same object
>>> t1.class_attr.append(1)  # alter via t1
>>> t2.class_attr
[1]  # see the changes via t2

However, you can override the class attribute with an instance attribute:

>>> t1.class_attr = []
>>> t1.class_attr is t2.class_attr
False

so if you need to replace the class attribute (rather than alter it in-place, as the append did) you should do so via the class, not the instance (in this case, Test.class_attr = [] would have affected both t1 and t2).

Sign up to request clarification or add additional context in comments.

2 Comments

where did you learn Python OOP? All the documentation I've read has never mentioned anything like what you pointed out. Did you read some particular book or tutorial?
@renatov I can't answer specifically, but note that this is covered in e.g. the official Python tutorial: docs.python.org/2/tutorial/…
1
class MyClass():
    i = 1

inst = MyClass()

All attributes of a class are stored in __dict__. It contains i (in addition to a bunch of other things):

>>> MyClass.__dict__
mappingproxy({'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'__module__': '__main__', '__dict__': <attribute '__dict__' of 'MyClass'
 objects>, 'i': 1, '__doc__': None})

The instance does not have any attributes:

>>> inst.__dict__
{}

If i cannot be found in inst.__dict__ the search continues in MyClass.__dict__. Even though it looks a bit like the instance has an attribute i, it actually exist in the class only.

As soon as you assign to the instance:

inst.i = 10

the this changes:

>>> inst.__dict__
{'i': 10}

Now, the instance has its own attribute.

2 Comments

Great answer, thanks! The OOP part in Python is very confusing to me. I'll start using the __dict__ to check what is created and what is not.
@renatov note that you can have __slots__ instead of __dict__, and the built-in types don't have either, so this isn't always possible

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.