Iterating over objects of a class
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
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 :) Diez -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
On Dec 24, 10:52 pm, Diez B. Roggisch de...@nospam.web.de 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 :) Diez 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
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
Re: Iterating over objects of a class
En Wed, 24 Dec 2008 16:18:55 -0200, Kottiyath n.kottiy...@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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
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 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 Thank you very much, Gabriel. I am very thankful to everyone. -- http://mail.python.org/mailman/listinfo/python-list
Re: Iterating over objects of a class
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.dani...@acm.org -- http://mail.python.org/mailman/listinfo/python-list