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}
现在,实例有自己的属性。
我需要一种方法来在 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}
现在,实例有自己的属性。