Iterating over objects of a class

MRAB google at mrabarnett.plus.com
Wed Dec 24 19:04:16 CET 2008


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.



More information about the Python-list mailing list