自定义类内部的Python生成器

问题描述 投票:0回答:2

我正在学习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
2个回答
0
投票

我认为您希望在生成器方法中使用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

0
投票

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

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

快乐编码!

© www.soinside.com 2019 - 2024. All rights reserved.