Python генератор внутри пользовательского класса - PullRequest
0 голосов
/ 28 мая 2020

Я изучаю Python и пытаюсь понять, почему функция, содержащая оператор yield в настраиваемом классе, не работает должным образом. Моя цель состоит в том, чтобы функция действовала как генератор; то есть он возвращает итератор генератора, который затем может использоваться в операторе for.

Класс определяется следующим образом:

class inclusive_range:

    def __init__(self, num):
        self._start = 0
        self._step = 1
        self._stop = num
        self._next = self._start

    # iterator implementation - would like to avoid this
    # def __iter__(self):
    #     return self
    #
    # def __next__(self):
    #     if self._next > self._stop:
    #         raise StopIteration
    #     else:
    #         _r = self._next
    #         self._next += self._step
    #         return _r

    # generator implementation - trying to get this to work
    def generator(self):
        if self._next < self._stop:
            _r = self._next
            self._next += self._step
            yield _r

Реализация итератора (закомментирована) работает должным образом при запуске этого оператора в основной программе:

for i in inclusive_range(10):
   print(i)

, где результат является ожидаемым (печатает числа от 0 до 10 включительно).

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

for i in inclusive_range(10).generator():
   print(i)

Результатом является только одно число 0. Сначала я подумал, что вызов generator () не возвращает итератор, как ожидалось, поэтому я использовал отладчик для исследования:

n = inclusive_range(10)

# I pulled up the "evaluate expression" window in the debugger and did the following:

n.generator().__next()__ # prints 0
n.generator().__next()__ # prints 1!
n.generator().__next()__ # prints 2!
n.generator().__next()__ # prints 3!

# ...and so on until StopIteration is raised.

Итак, мой вопрос ... похоже, он работает так, как я ожидал, в отладчике, почему в противном случае он возвращает только первое значение?

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Проблема в том, что генератор неправильно сформирован. Вам понадобится al oop, что yield является желаемым значением при обновлении состояния объекта, чтобы подготовиться к yield следующему значению. Короче говоря, вам просто нужно заменить if на while в generator(self), и вы должны быть готовы к go! Этот код сработал для меня (закомментированный код удален для ясности):

class inclusive_range:
    def __init__(self, num):
        self._start = 0
        self._step = 1
        self._stop = num
        self._next = self._start

    # generator implementation - trying to get this to work
    def generator(self):
        while self._next < self._stop:  # <-- while instead of if
            _r = self._next
            self._next += self._step
            yield _r

И тест:

> for i in inclusive_range(10).generator(): 
    print(i) 
0
1
2
3
4
5
6
7
8
9

Happy Coding!

1 голос
/ 28 мая 2020

Я думаю, вам нужен while l oop вместо оператора if в вашем методе генератора:

# generator implementation - trying to get this to work
def generator(self):
    while self._next <= self._stop:
        _r = self._next
        self._next += self._step
        yield _r
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...