【问题标题】:Python generator inside custom class自定义类中的 Python 生成器
【发布时间】:2020-05-28 02:03:22
【问题描述】:

我正在学习 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(包括 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.

所以我的问题是......它似乎在调试器中正常工作,为什么它只返回第一个值?

【问题讨论】:

  • 顺便说一句,“

标签: python generator


【解决方案1】:

问题源于生成器没有正确形成。您将需要一个循环,其中yield 是所需的值,同时更新对象状态以准备yield 下一个值。简而言之,您只需在generator(self) 中将if 替换为while 就可以了!这段代码对我有用(为了清楚起见,注释掉了代码):

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

编码愉快!

【讨论】:

  • 谢谢,因为生成器的执行在屈服后暂停。
  • 完全正确 - 生成器是在返回(产生)值后保持其状态的函数。在下一次调用中,它们从原来的位置恢复,并且应该以这样的方式形成 yield 每次所需的下一个值。
【解决方案2】:

我认为您希望在生成器方法中使用 while 循环而不是 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

【讨论】:

    猜你喜欢
    • 2019-10-04
    • 2019-02-15
    • 2020-02-21
    • 2012-01-26
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多