Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over object instances of a given class in Python

Tags:

Given a class that keeps a registry of its Objects:

class Person(object):
   __registry = []

   def __init__(self, name):
       self.__registry.append(self)
       self.name = name

How would I make the following code work (without using Person.__registry):

for personobject in Person:
    print personobject

While researching I found a hint that one could go for a __metaclass__ with a __getitem__-method. Any ideas how this would look like?

like image 704
Titusz Avatar asked Apr 11 '09 11:04

Titusz


People also ask

How do you iterate over an object in Python?

You can create an iterator object by implementing the iter built-in function to an iterable. An iterator can be used to manually loop over the items in the iterable. The repeated passing of the iterator to the built-in next function returns successive items in the stream.

How do you iterate over a class in Python?

Create an Iterator To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object. As you have learned in the Python Classes/Objects chapter, all classes have a function called __init__() , which allows you to do some initializing when the object is being created.

What does __ ITER __ do in Python?

The __iter__() function returns an iterator for the given object (array, set, tuple, etc. or custom objects). It creates an object that can be accessed one element at a time using __next__() function, which generally comes in handy when dealing with loops.

Can we iterate class in Python?

If you want to iterate over the class, you have to define a metaclass which supports iteration. . This way the values will only kept as long as there is a "strong" reference keeping it, such as a in this case.


2 Answers

You can make your class object iterable with a simple metaclass.

class IterRegistry(type):
    def __iter__(cls):
        return iter(cls._registry)

class Person(object):
    __metaclass__ = IterRegistry
    _registry = []

    def __init__(self, name):
        self._registry.append(self)
        self.name = name

(I have also changed __registry to _registry to make it easier to access from the metaclass). Then,

>>> p = Person('John')
>>> p2 = Person('Mary')
>>> for personobject in Person:
...     print personobject
...
<person.Person object at 0x70410>
<person.Person object at 0x70250>
like image 185
dF. Avatar answered Sep 19 '22 16:09

dF.


First, do not use double __ names. They're reserved for use by Python. If you want "private" use single _.

Second, keep this kind of thing as simple as possible. Don't waste a lot of time and energy on something complex. This is a simple problem, keep the code as simple as possible to get the job done.

class Person(object):
    _registry = []

    def __init__(self, name):
        self._registry.append(self)
        self.name = name

for p in Person._registry:
    print p
like image 41
S.Lott Avatar answered Sep 20 '22 16:09

S.Lott