收集类变量中的所有实例总是不好的吗?

时间:2015-07-09 06:20:34

标签: python class global-variables class-method class-members

考虑两个版本的简单天气模型,它存储云的位置:

class cloud:
    def __init__(self, x, y):
        self.x = x
        self.y = y

collection = []
collection.append(cloud(1,2))
collection.append(cloud(4,6))

def update_all_clouds(collection):
    for c in collection:
        cloud.x += 1
        cloud.y += 1

update_all_clouds(collection)

VS

class cloud:
    collection = []
    def __init__(self, x, y)
        self.x = x
        self.y = y
        cloud.collection.append(self)
    @classmethod
    def update_all(cls):
        for c in cloud.collection:
            c.x += 1
            c.y += 1
cloud(1,2)
cloud(4,6)
cloud.update_all()

这基本上受到了惩罚 Is it bad to store all instances of a class in a class field? 但是这里强调的是对所有实例起作用的类方法。 对于第二种方法提供的最后三行的简单性,没有什么可说的吗?

我知道另一种方法是创建一个类似于列表的类,例如,集合并给出像update_all()这样的类方法,但对我来说它似乎没有那么好。

3 个答案:

答案 0 :(得分:3)

这个问题可以简单地简化为关于使用全局变量的问题,因为可变类类成员只是不同命名空间中的全局变量。

所有arguments against using global variables也适用于此。

答案 1 :(得分:3)

通常,这很糟糕,是的,原因很简单,因为列表中的对象几乎永远引用了它们。存在对对象的引用可防止其被垃圾收集。所以你的类型的对象基本上永远存在(直到程序终止)并且它们占用的内存永远不会被释放。

当然,如果您有非常具体的需求,并完全控制对象的创建时间,那么可以这样做。但总的来说explicit is better than implicit,所以最好有一个实际的集合来添加这些元素。该集合甚至可以存在于该类型中,因此您可以这样做:

obj = Cloud(…)
Cloud.add(obj)

# or even
obj = Cloud(…).persistInType()

您也可以使用weak references来避免上述问题,但这是额外的开销,管理起来有点复杂。所以,请帮自己一个忙,并手动收集对象。

答案 2 :(得分:3)

考虑到 explicit比隐式更好(参见The Zen of Python),也许最好的方法是拥有两个类:Mage::getModel('directory/currency')->format( $yourprice, array('display'=>Zend_Currency::NO_SYMBOL), false ); Cloud。这将允许您编写如下代码:

CloudCollection