Как использовать __getitem__ и __iter__ и возвращать значения из словаря?

У меня есть объект со словарем, к которому я хочу получить доступ через __getitem__, а также итерацию (только значения, ключи не имеют значения), но я не уверен, как это сделать.

Например:

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
>>> 

Как мне сказать, чтобы просто вернуть object для каждого элемента в словаре (ключ не имеет значения)?

Ответы

Ответ 1

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

Ответ 2

Добавьте этот метод в библиотеку:

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

Это делегирует итерацию dict, которая имеет простой способ для итерации значений. Читайте об протоколе итератора, который состоит из методов __iter__ (по всем итерам) и next (__next__ в 3.x) (только для итераторов).

Ответ 3

>>> 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'>

Ответ 4

Вы можете вернуть итератор из своих внутренних данных:

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

itervalues() возвращает итератор в значения словаря.

Если вы хотите большего контроля, вы можете сделать __iter__ функцию генератора

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

в этом случае этот генератор дает то же самое, что и итератор в первом примере.

Ответ 5

Рассматривали ли вы использование UserDict mixin?

Ответ 6

__getitem__(self,key), где ключ является целым числом, так как ваш self.books - это словарь, и вы не можете сделать self.books[integer]

например:

>>>d = {'a':'sdsdsd','b':'sfsdsd'}
>>d[0]

d[0]
Traceback (most recent call last):
  File "<console>", line 1, in <module>
KeyError: 0

протокол итерации выглядит следующим образом:

Протокол итератора состоит из двух методов. Метод __iter__(), который должен возвращать объект итератора и метод next(), который возвращает следующий элемент из последовательности. ранее, когда метод __iter__ не определялся, он возвращался к __getitem__, последовательно вызывая __getitem__ с увеличением значений до тех пор, пока не выдаст ошибку индекса за пределами диапазона.