Iterating over objects of a class

Kottiyath n.kottiyath at gmail.com
Wed Dec 24 13:18:55 EST 2008


On Dec 24, 11:04 pm, MRAB <goo... at 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?



More information about the Python-list mailing list