On Dec 24, 11:04 pm, MRAB <goo...@mrabarnett.plus.com> wrote: > Diez B. Roggisch wrote: > > Kottiyath schrieb: > >> Hi, > >> How can I iterate over all the objects of a class? > >> I wrote the code like following: > >> class baseClass(object): > > > Consider adopting PEP 8 coding conventions. > > >> __registry = [] > > >> def __init__(self, name): > >> self.__registry.append(self) > >> self.name = name > > >> def __iter__(self): > >> baseClass.item = 0 > >> return self.__registry[0] > > >> def next(self): > >> if baseClass.item >= len(self.__registry): > >> raise StopIteration > >> baseClass.item += 1 > >> return self.__registry[baseClass.item - 1] > > >> For testing, create the following objects- > >> a = baseClass("Test1") > >> b = baseClass("Test2") > > >> class subClass (baseClass): > >> pass > >> c = subClass("Test3") > > >> ---->Actual Iteration<---- > >> for i in a: > >> print i.name > > >> Test1 > >> Test2 > >> Test3 > > >> --------------------------------------------------- > >> I see the following problems in the code: > >> 1. I have to iterate over any of the objects. For correctness, I > >> wanted to iterate over the class, like > >> for i in baseClass(): > >> do x > >> but that will will create one more object - which I do not want. > > >> 2. If the subclass wants to do somethings in its constructor, I am not > >> sure how to update the registry. > >> class subClass (baseClass): > >> def __init__(self, name): > >> **do something** > >> super.init(self, name) ----> This errors out, saying it needs > >> super, not subClass > > > You don't show the actual traceback, however the idiom for invoking > > super for new-style-classes is > > > super(subClass, self).__init__(name) > > > for your case. > > >> Another method I thought of implementing it was using generators - > >> where-in baseClass.objects() is a generator which will yield the > >> objects one by one - but even then the second issue remains. > >> If somebody can help me out, I would be very thankful. > > > Using a generator or not isn't the issue here. > > > What you need is a *class*-based access, not instance-based. There are > > various methods to accomplish this. The simplest is to ditch the > > obnoxious __registry as name, and just do > > > class BaseClass(object): > > > REGISTRY = [] > > > Then iterating is a simple matter of > > > for instance in BaseClass.REGISTRY: > > ... > > > Case solved. Alternatively, if you insist on the concept of privacy for > > that registry, you can use a classmethod: > > > class BaseClass(object): > > > �...@classmethod > > def registry(cls): > > for i in cls.__registry: > > yield i > > > Last but not least you *could* go for a __metaclass__ with an > > __getitem__-method, that makes thinks look fancy because you then can do: > > > for instance in BaseClass: > > ... > > > I leave it as an exercise to you - gotta go christmas dining now :) > > The other thing to remember is that because the 'registry' contains > references to the instances, they won't be garbage collected.
Is there any other way out in this case? I have factory methods - and I have to loop over them - sort of Chain of Responsibility pattern. Having a registry inside the class instance and looping through them was the only clean thing I could think of. I understand that garbage collection would be an issue - but is there any way out? -- http://mail.python.org/mailman/listinfo/python-list