Iterating over objects of a class

2008-12-24 Thread Kottiyath
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

2008-12-24 Thread Diez B. Roggisch

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

2008-12-24 Thread MRAB

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

2008-12-24 Thread Kottiyath
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

2008-12-24 Thread Kottiyath
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

2008-12-24 Thread Gabriel Genellina
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

2008-12-24 Thread Kottiyath
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

2008-12-24 Thread Scott David Daniels

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