Python - 静态类变量

时间:2017-04-03 14:08:01

标签: python class static

我来自C ++背景,并且经常使用静态变量来减少必须初始化的时间变量的数量(特别是如果初始化需要很长时间)。因此,从StackOverflow上的其他帖子中,人们建议使用静态类变量,如下所示:

class MyClass(object):

    StaticList1 = [...] # Very large list
    StaticList2 = [...] # Very large list

现在,如果在程序执行过程中至少存在一个MyClass实例并且列表只创建一次,那么这很好。但是,如果在执行的某个阶段没有MyClass的实例,Python似乎删除了静态列表(我假设因为引用计数器降为0)。

所以我的问题是,如果没有使用外部模块初始化StaticList1和StaticList2一次(第一次使用它们)并且永远不会删除它们,即使在程序存在之前没有MyClass的实例,也没有任何简单的方法(或者你手动删除列表??

编辑:

也许我过分简化了这个问题。我在做什么:

class MyClass(object):

    StaticList = None

    def __init__(self, info):
        if self.StaticList == None:
            print "Initializing ..."
            self.StaticList = []
            # Computationally expensive task to add elements to self.StaticList, depending on the value of parameter info

    def data(self):
        return self.StaticList

我从另一个脚本导入模块并有一个这样的循环:

import myclass
for i in range(10000):
    m = myclass.MyClass(i)
    d = m.data()
    # Do something with d.

静态列表的初始化大约需要200到300毫秒,并且在循环的每次迭代中执行,因此循环需要很长时间才能完成。

1 个答案:

答案 0 :(得分:3)

虽然您的类确实有一个名为StaticList的静态字段,但您实际上正在初始化并使用同名的实例字段,因为您有self限定符使用。我认为如果您使用MyClass.StaticList初始化并访问它,您的代码将正常工作。

通常,通过Python的名称查找,您可以通过实例访问类字段,就好像它是该实例上的实例字段(例如self.StaticList),只要您实际上并没有在该实例上设置同名的实例字段。从那一刻起,实例字段会影响类字段(即self.StaticList会找到您的新值,而MyClass.StaticList仍会引用您的类值。

作为解说员新鲜的例子:

>>> class A(object):
...  v=2      # static initialization
...
>>> A.v
2
>>> a=A()     # get an instance, and
>>> a.v       # get the static value via the instance:
2
>>> a.v = 7   # but now set 'v' on the instance, and ...
>>> a.v       # we will get the instance field's value:
7
>>> A.v       # the static value is still the old:
2
>>> b=A()     # and other instances of the class ...
>>> b.v       # will use the same old static value:
2

实例变量a.v最初等于A.v,但通过明确设置a.v=7,您将在该实例中“分离”它们。

虽然这意味着,原则上,你可以使用静态类字段MyClass.Values以及同名的实例字段xyz.Values,这是经常因这种混乱而气馁。

作为单独的评论,您可以考虑将data方法注释为@staticmethod(并移除移动中的self参数),并将其称为MyClass.data()事实清楚的是,你会在每次通话时回到同一个列表实例。