Если вы хотите перебрать класс , вам необходимо определить метакласс, поддерживающий итерацию.
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
, а затем сделать
by_id = weakref.WeakValueDictionary()
. Таким образом, значения будут сохраняться до тех пор, пока в этом случае имеется «сильная» ссылка, например a
. После del a
есть только слабые ссылки, указывающие на объект, поэтому они могут быть gc'ed.
В связи с предупреждением относительно WeakValueDictionary()
с, я предлагаю использовать следующие:
[...]
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
объекта.
Пожалуйста, покажите свой метод класса '__iter__' и пример его отказа. – Marcin
Помните, однако, что вы никогда не избавитесь от своих экземпляров. Вы должны работать со слабыми ссылками. – glglgl
К счастью, время жизни экземпляров не является проблемой. Но я хотел бы посмотреть, как это должно быть сделано. – xorsyst