views:

80

answers:

5

I have an object with a dictionary that I want to access via __getitem__ as well as iterate over (values only, keys don't matter) but am not sure how to do it.

For example:

Python 2.5.2 (r252:60911, Jul 22 2009, 15:33:10) 
>>> class Library(object):
...   def __init__(self):
...     self.books = { 'title' : object, 'title2' : object, 'title3' : object, }
...   def __getitem__(self, i):
...     return self.books[i]
... 
>>> library = Library()
>>> library['title']
<type 'object'>
>>> for book in library:
...   print book
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __getitem__
KeyError: 0
>>>

How do I tell it to simply return the object for each item in the dictionary (the key doesn't matter) ?

+4  A: 
def __iter__(self): return self.books.itervalues()
Alex Martelli
Thanks - I knew it was something easy but was having the hardest time tracking that down! Appreciate it.
thornomad
A: 

Add this method to Library:

def __iter__(self):
  return self.books.itervalues()

This delegates iteration to the dict, which has an easy method to iterate values. Read about the iterator protocol, which consists of __iter__ (on all iterables) and next(__next__ in 3.x) (only on iterators) methods.

Roger Pate
+2  A: 
>>> class Library(object):
...     def __init__(self):                                                     
...             self.books = { 'title' : object, 'title2' : object, 'title3' : object, }
...     def __getitem__(self, i):
...             return self.books[i]
...     def __iter__(self):
...             return self.books.itervalues()
... 
>>> library = Library()
>>> library['title']
<type 'object'>
>>> for book in library:
...     print book
... 
<type 'object'>
<type 'object'>
<type 'object'>
Jason Baker
A: 

Have you considered using the UserDict mixin?

Suppressingfire
+1  A: 

You can return an iterator from your inner data:

class Library (object):
  ...
  def __iter__(self):
    return self.books.itervalues()

itervalues() returns an iterator to the values of the dictionary.

If you want more control, you can make __init__ a generator function

class Library (object):
  ...
  def __iter__(self):
    for title in self.books:
      yield self.books[title]

in this case, this generator yields the exact same as the iterator in the first example.

kaizer.se