Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Iterating over objects of a class

18 views
Skip to first unread message

Kottiyath

unread,
Dec 24, 2008, 12:37:31 PM12/24/08
to
Hi,
How can I iterate over all the objects of a class?
I wrote the code like following:
class baseClass(object):
__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

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.

Regards
K

Diez B. Roggisch

unread,
Dec 24, 2008, 12:52:50 PM12/24/08
to
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.

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 :)

Diez

MRAB

unread,
Dec 24, 2008, 1:04:16 PM12/24/08
to pytho...@python.org
The other thing to remember is that because the 'registry' contains
references to the instances, they won't be garbage collected.

Kottiyath

unread,
Dec 24, 2008, 1:15:29 PM12/24/08
to

Thank you Very much, Diez. I was able to do the Generator and the
super part of it, but I never even thought of the metaclass option.
I will try it out. Thank you very much.
Merry Christmas.
P.S - >Also, I will use the PEP 8 coding conventions

Kottiyath

unread,
Dec 24, 2008, 1:18:55 PM12/24/08
to

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?

Gabriel Genellina

unread,
Dec 24, 2008, 1:48:06 PM12/24/08
to pytho...@python.org
En Wed, 24 Dec 2008 16:18:55 -0200, Kottiyath <n.kot...@gmail.com>
escribió:

>> 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?

You may keep all that structures - just use weak references (see the
weakref module).
There isn't a WeakList nor WeakSet out-of-the-box but you may use a
WeakKeyDictionary (set the value to anything, None by example).

--
Gabriel Genellina

Kottiyath

unread,
Dec 24, 2008, 2:08:27 PM12/24/08
to
On Dec 24, 11:48 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Wed, 24 Dec 2008 16:18:55 -0200, Kottiyath <n.kottiy...@gmail.com>  

Thank you very much, Gabriel.
I am very thankful to everyone.

Scott David Daniels

unread,
Dec 24, 2008, 2:48:57 PM12/24/08
to
Kottiyath wrote:
> ...

> 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?

Search for weakref in the documentatione.
In this case, I'd use a WeakValueDictionary() from id(obj) to obj.
Note id(obj) is guaranteed to be unique for all objects in existance,
but the id of a collected object may match the id of a new object.

>>> import weakref
>>> d = weakref.WeakValueDictionary()
>>> vs = [Int(n) for n in range(3, 500, 70)]
>>> for n in vs:
d[id(n)] = n
v = Int(n+1)
d[id(v)] = v
>>> for obj in d.values(): # values is safer than itervalues
print obj
>>> # note the above was the following, which fails:
>>> for v in d.values(): # values is safer than itervalues
print v


For extra credit, explain why values is better.

--Scott David Daniels
Scott....@Acm.Org

0 new messages