Python: Почему я не могу перебрать список? Мой класс исключений потерян? - PullRequest
5 голосов
/ 02 февраля 2010

Я уже рассматривал этот вопрос: Итераторы Python - как динамически назначать self.next в новом классе стилей?

но это не помогает мне, потому что я хочу перебрать атрибут ошибки, который является списком (то есть уже итерируемым), без необходимости явно использовать атрибут. Я хочу сделать это:

class SCE(Exception):
    """
    An error while performing SCE functions.
    """
    def __init__(self, value=None):
        """
        Message: A string message or an iterable of strings.
        """
        if value is None:
            self._values = ['A general SCE error has occured.']
        elif isinstance(value, str):
            self._values = [value]
        else:
            self._values = list(value)

    def __iter__(self):
        return self._values

    def __repr__(self):
        return repr(self._values)

Тем не менее, в оболочке я получаю это:

try:
    raise CSE(['error one', 'error two'])
except CSE, e:
    for i in e:
        print(i)
Traceback (most recent call last):
  File "(stdin)", line 1, in (module)
TypeError: iter() returned non-iterator of type 'list'

Я знаю, что могу удалить _ из _values, а затем перебрать e.values, но я не хочу этого делать, так как это представляет реализацию моего класса Exception.

Ответы [ 3 ]

20 голосов
/ 02 февраля 2010

Метод __iter__ должен возвращать объект итератора, но вы возвращаете объект списка. Используйте

def __iter__(self):
    return iter(self._values)

вместо того, чтобы исправить это. Из документации на object.__iter__ (моя подсветка):

Этот метод вызывается, когда для контейнера требуется итератор. Этот метод должен возвращать новый объект итератора , который может перебирать все объекты в контейнере.

5 голосов
/ 02 февраля 2010
def __iter__(self):
    return iter(self._values)

Или более общий:

def __iter__(self):
    for x in self._values:
        yield x
1 голос
/ 02 февраля 2010

__iter__ должен возвращать итератор, а не список.

Попробуйте это:

    def __iter__(self):
        return iter(self._values)

Вы также можете сделать:

    def __iter__(self):
        for val in self._values:
            yield val

Но я не могу придумать причину, по которой вам нужно это сделать вместо использования iter()

...