Python 中的可序列化静态 class 变量

Serializable Static class variables in Python

是否可以在 python 中包含可序列化的静态 class 变量或方法? 举个例子,假设我有以下代码片段:

import pickle
class Sample:
    count = 0 # class variable
    def __init__(self, a1=0, a2=0):
        self.a = a1
        self.b = a2
        Sample.count += 1

#MAIN
f = open("t1.dat", "wb")
d = dict()
for i in range(10):
    s = Sample(i, i*i)
    d[i] = s
pickle.dump(d,f)
print "Sample.count = " + str(Sample.count)
f.close()

输出为:

Sample.count = 10

现在,我有另一个类似于上面的 reader 程序:

import pickle
class Sample:
    count = 0 # class variable
    def __init__(self, a1=0, a2=0):
        self.a = a1
        self.b = a2
        Sample.count += 1

#MAIN
f = open("t1.dat", "rb")
d = pickle.load(f)
print "Sample.count = " + str(Sample.count)

输出为:

Sample.count = 0

我的问题是: 如何从我的文件中加载 class 变量?换句话说,如何序列化 class 变量?如果直接不可能,还有其他选择吗?请建议。 由于无法选择 class 变量,作为替代方案,我在读取文件时使用了主要部分的代码片段,如下所示:

#MAIN
f = open("t1.dat", "rb")
d = pickle.load(f)
Sample.count = len(d.values())
print "Sample.count = " + str(Sample.count)

现在的输出是:

Sample.count = 10

这是可以接受的解决方案吗?还有其他选择吗?

引用 "What can be pickled and unpickled?"

上的部分

Similarly, classes are pickled by named reference, so the same restrictions in the unpickling environment apply. Note that none of the class’s code or data is pickled, so in the following example the class attribute attr is not restored in the unpickling environment:

class Foo:
    attr = 'a class attr'

picklestring = pickle.dumps(Foo)

所以因为 attr,或者在你的情况下 count,是 class 定义的一部分,它永远不会被腌制。在您的 'write' 示例中,您打印的 Sample.count 确实存在但首先没有被腌制。

您可以在每个实例中将 Sample.count 存储为 _count 并放入 Sample.count = self._count。但请记住,由于您的 ddict,它们可能会以任何顺序解开。所以本质上这是行不通的。

您需要将 __setstate__ 添加到您的 class 自定义它腌制的方式并放入一些标志值(如 _count),然后您在 __getstate__. 中操作(通过任何一致工作的逻辑)(编辑:除非您将 count 存储在全局变量中并在 [=23 中访问它,否则对给定的问题没有帮助=] 并在每次解封对象时进一步操作。)

另一种可能的解决方法,但 yuck:向您的 dict d 添加一个变量,以便它也被腌制。当你读回来的时候,用Sample.count = d['_count']恢复。所以在 pickle.dump(d,f) 之前,当你腌制时,做 d['_count'] = Sample.count.

重要警告:这实际上不允许您腌制 Sample.count,因为您实际腌制的 (d) 是 Sample 的字典。

编辑:您作为变通方法提出的 Sample.count = len(d.values()) 非常 特定于您的用例 而不是 class 中的属性 一般.