Python 中的静态 class 变量,不会为每个实例复制

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

我需要一种方法来在 Python 中创建只有 class 才有的静态 class 变量。我无法承受为每个实例一遍又一遍地创建这个变量,因为目标 class 变量将是一个巨大的只读数据结构。每个实例都必须能够通过 class 出于只读目的访问它,但由于它是大量数据并且会有数千个实例,我无法承受每个实例都会创建此副本的另一个副本又是数据结构。

我找到了 this question,但它没有解决我的问题,因为建议的静态 class 变量是为每个实例创建的:

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

换句话说,我正在寻找静态 class 变量,如 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     
?>

这正是我所需要的,静态 class 变量只为 class 创建一次,所有实例都可以通过 class 访问它,但是这个静态 class 变量不会为每个新实例一遍又一遍地创建。是否可以在 Python?

中创建像这样的静态 class 变量

PS:如果我不使用 OOP,我现在有一些解决方法,但如果我能找到一个好的且清晰易读的 OOP 解决方案,那么它在整个项目中会更有意义。

the static class variable suggested is created for each instance

这是错误的,你可以很容易地证明:

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

但是,您可以覆盖具有实例属性的class属性:

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

因此,如果您需要 替换 class 属性(而不是像 append 那样就地更改它),您应该这样做通过 class,而不是实例(在这种情况下,Test.class_attr = [] 会同时影响 t1 t2)。

class MyClass():
    i = 1

inst = MyClass()

class 的所有属性都存储在 __dict__ 中。它包含i(除了一堆其他东西):

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

实例没有任何属性:

>>> inst.__dict__
{}

如果在 inst.__dict__ 中找不到 i,则在 MyClass.__dict__ 中继续搜索。尽管它看起来有点像实例具有属性 i,但它实际上只存在于 class 中。

一旦分配给实例:

inst.i = 10

这个变化:

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

现在,实例有自己的属性。