Ответ 1
Если вы хотите перебирать класс, вам нужно определить метакласс, поддерживающий итерацию.
x.py:
class it(type):
def __iter__(self):
# Wanna iterate over a class? Then ask that class for iterator.
return self.classiter()
class Foo:
__metaclass__ = it # We need that meta class...
by_id = {} # Store the stuff here...
def __init__(self, id): # new isntance of class
self.id = id # do we need that?
self.by_id[id] = self # register istance
@classmethod
def classiter(cls): # iterate over class by giving all instances which have been instantiated
return iter(cls.by_id.values())
if __name__ == '__main__':
a = Foo(123)
print list(Foo)
del a
print list(Foo)
Как вы можете видеть в конце, удаление экземпляра не окажет никакого влияния на сам объект, потому что он остается в by_id
dict. Вы можете справиться с этим, используя weakref
, когда вы
import weakref
а затем do
by_id = weakref.WeakValueDictionary()
. Таким образом, значения будут сохраняться до тех пор, пока в этом случае существует "сильная" ссылка, например a
. После del a
есть только слабые ссылки, указывающие на объект, поэтому они могут быть gc'ed.
Из-за предупреждения относительно WeakValueDictionary()
s, я предлагаю использовать следующее:
[...]
self.by_id[id] = weakref.ref(self)
[...]
@classmethod
def classiter(cls):
# return all class instances which are still alive according to their weakref pointing to them
return (i for i in (i() for i in cls.by_id.values()) if i is not None)
Выглядит немного сложнее, но гарантирует, что вы получите объекты, а не объект weakref
.