0

there exists following class.

class Reaction(object):
    Var1 = "lorem"
    Var2 = "impsum"
    Var3 = "dolor"

I'd like to iterate over the attributes of this class, like in following code.

for value in Reaction:
    print value

This should produce following output.

lorem
ipsum
dolor

I've already found this topic: How to iterate over a the attributes of a class, in the order they were defined?, but it doesn't really help me.

How can I make my class iterable?

EDIT: I thought of something similar like in this post: Build a Basic Python Iterator.

Community
  • 1
  • 1
wewa
  • 1,628
  • 1
  • 16
  • 35

3 Answers3

3

If you really need an object whose members are accessible via dot notation but you still want to iterate through them, you need a namedtuple.

Reaction = collections.namedtuple('Reaction', ['Var1', 'Var2', 'Var3'])
reaction = Reaction('lorem', 'ipsum', 'dolor')
for value in reaction:
    print value
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Sorry I forgot to mention that I use Python version 2.5.1 and there `collections` doesn't have the method `namedtuple` – wewa Jul 25 '12 at 11:34
1

First off, what you are trying is a little unusual - normally, a dict is used for this kind of thing

Reaction = {
   var1: "Lorem",
   var2: "Ipsum",
   var3: "Dolor"
}

If for some reason you still prefer your method, you can use inspect.getmembers(). A helper function could look like this

def attributes(class_):
    for name, value in inspect.getmembers(class_):
        if not name.startswith("__"):
             yield name, value

Then you can do

for name, value in attributes(Reactor):
    # do stuff
Otto Allmendinger
  • 27,448
  • 7
  • 68
  • 79
1
>>> for k, v in Reaction.__dict__.iteritems():
...     if not k.startswith('__'):
...         print v
... 
lorem
dolor
impsum

Or better:

>>> import inspect
>>> class Reaction(object):
...     Var1 = "lorem"
...     Var2 = "impsum"
...     Var3 = "dolor"
...     def __iter__(self):
...         return (v for k, v in inspect.getmembers(self) if not k.startswith('__'))
... 
>>> for value in Reaction():
...     print value
... 
lorem
impsum
dolor
applicative_functor
  • 4,926
  • 2
  • 23
  • 34
  • Your code does almost the things I want. But is there no possibility to get it work with `for value in Reaction: print value` (without the `.__dict__` method)? – wewa Jul 25 '12 at 11:40
  • @no it isn't - you could however build a helper method returning the class attributes – Otto Allmendinger Jul 25 '12 at 11:42
  • @OttoAllmendinger: Could you explain this to me. Is this similar to http://stackoverflow.com/questions/19151/build-a-basic-python-iterator? – wewa Jul 25 '12 at 11:43
  • @wewa: yes, although there is an easier way (see my answer) – Otto Allmendinger Jul 25 '12 at 12:38