views:

60

answers:

2

I might be doing this wrong, if I am, let me know, but I'm curious if the following is possible:

I have a class that holds a number of dictionaries, each of which pairs names to a different set of objects of a given class. For example:

items = {"ball" : ItemInstance1, "sword" : ItemInstance2}
people = {"Jerry" : PersonInstance1, "Bob" : PersonInstance2, "Jill" : PersonInstance3}

My class would then hold the current items and people that are availible, and these would be subject to change as the state changes:

Class State:
    def __init__(self, items, people):
        self.items = items
        self.people = people

I would like to define a iter() and next() method such that it iterates through all of the values in its attributes. My first question is whether or not this is possible. If it is, will it be able to support a situation as follows:

I define items and people as above then:

state = State(items, people)
for names, thing in state:
    print name + " is " + thing.color

items[cheese] = ItemInstance3
for names, thing in state:
    print name + " weighs " + thing.weight

While I feel like this would be usefull in the code I have, I don't know if it's either possible or the right approach. Everything I've read about user defined iterators has suggested that each instance of them is one use only.

+2  A: 

If I understand you question correctly then adding the following method to your class should do it:

def __iter__(self):
    import itertools
    return itertools.chain(self.items.itervalues(), self.people.itervalues())

This chains together two iterators, and the ones chosen here are for the values of items and the values of people.

To make your later code work though, you'll want to iterate over the items - the key-value pairs. In which case this would do it:

def __iter__(self):
    import itertools
    return itertools.chain(self.items.iteritems(), self.people.iteritems())
awatts
+1  A: 

There are lots of ways to do what you want. You can indeed have such a State class, and implement the iter() method (http://docs.python.org/library/stdtypes.html).

You could also create a generator function:

   def iterate_two(l1, l2):
      for k in l1:
         yield k, l1[k]
      for k in l2:
         yield k, l2[k]

You can use itertools.chain. You can use list comprehensions and generator expressions. Etc.

I, personally, wouldn't create the State class as you suggest, if all it is is an iterator mechanism - I'd probably use a list comprehension.

Colin