简体   繁体   中英

Static class variable in Python that isn't copied for each instance

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.

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 ).

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM