Is it always bad to collect all instances in a class variable?

Consider two versions of a simple weather model which stores the location of clouds:

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

collection = []

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



class cloud:
    collection = []
    def __init__(self, x, y)
        self.x = x
        self.y = y
    def update_all(cls):
        for c in cloud.collection:
            c.x += 1
            c.y += 1

This has basically been punished here
Is it bad to store all instances of a class in a class field?
but there is an emphasis here on class methods which act on all instances.
Is there nothing to be said for the simplicity of the last three lines that the second approach affords?

I am aware that another approach would be creating a list-like class called, for example, collection and giving that class methods like update_all() but to me it doesn’t seem much better.

Best answer

In general, this is bad, yes, for the simple reason that the objects being in a list keeps a reference to them pretty much forever. There being a reference to an object prevents it from being garbage collected. So objects of your type essentially live forever (until the program terminates) and the memory they take up will never be freed.

Of course, if you have a very specific need for this, and are in full control of when the objects are created, you could do it like that. But in general explicit is better than implicit, so it’s a better idea to have an actual collection where you add those elements. That collection could even live in the type, so you could do:

obj = Cloud(…)

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

You could also use weak references to avoid the problem described above, but that’s additional overhead, and a bit more complicated to manage. So just do yourself a favor, and collect the objects manually.