python - 用类模拟产量

标签 python python-3.x generator yield

我有以下yield函数:

def yield_numbers(start=1, end=1e6):
    num = start
    while num <= end:
        yield num
        num += 1

我想构建一个类来复制 yield 表达式的最基本功能,以进一步了解它的工作原理。这是我到目前为止所拥有的:

class YieldNumbers:
    def __init__(self, start=1, end=1e6):
        self.start = int(start)
        self.end = int(end)
        self._current_val = None
        self._closed = False
    def __iter__(self):
        if self._closed: raise StopIteration
        return self
    def close(self):
        self._closed = True
    def send(self, value):
        return self.__next__(value)
    def throw(self, exc_type):
        assert isinstance(exc_type, Exception)
        return self.__next__(exc_type=exc_type)
    def __next__(self, value=None, exc_type=None):
        if self._closed: raise StopIteration
        if exc_type: raise exc_type
        self._current_val = value if value else self.start if not self._current_val else self._current_val + 1
        if self._current_val > self.end: self._closed=True; raise StopIteration
        return self._current_val

并使用它:

for i in YieldNumbers(start=1,end=3):
    print (i)
1
2 
3
>>> y=YieldNumbers()
>>> next(y)
1
>>> y.close()
>>> next(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 18, in __next__
StopIteration

这与 yield 的工作原理(在最基本的层面上)类似吗?如果没有,我在这里缺少什么?再次强调,这并不是要重新发明轮子或使某些东西变得健壮,而是更多地了解 yield 在概念层面上是如何工作的。

最佳答案

尽管您的示例中的行为相同,但这与 yield 的工作方式不同。从根本上来说,yield 会暂停生成器函数的执行,并在调用 next 时从同一位置恢复;并且生成器函数开始暂停,因此直到第一次调用next时才会执行初始代码。

将使用 yield 的代码转换为不使用 yield 的代码是可能的,但并不简单。为了模拟生成器的工作方式,我们需要实例知道它应该假装从哪里“恢复”,所以我们称之为 resume_point。我没有关心一些细节,例如将数据发送回生成器、异常处理或关闭;但你明白了。

class Example:
    def __init__(self, start, end):
        self.start = start
        self.end = end
        self.resume_point = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.resume_point == 0:
            # simulates the beginning of your generator function
            self.num = self.start
            # simulates checking the `while` loop condition
            if self.num <= self.end:
                # next time we should continue from the `yield`
                self.resume_point = 1
                # `return` simulates pausing the generator function
                return self.num
            # simulates the end of your generator function
            self.resume_point = 2
            raise StopIteration
        elif self.resume_point == 1:
            # simulates continuing from the `yield` in your generator function
            self.num += 1
            # simulates checking the `while` loop condition
            if self.num <= self.end:
                # redundant, but it shows what happens
                self.resume_point = 1
                # `return` simulates pausing the generator function
                return self.num
            # simulates the end of your generator function
            self.resume_point = 2
            raise StopIteration
        elif self.resume_point == 2:
            # simulates resuming from after your generator function returned
            self.resume_point = 2
            raise StopIteration

关于python - 用类模拟产量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60443037/

相关文章:

python - 如何在 sklearn 中编码分类变量?

python - 如何拆分带有参数的Python请求?

python - 值更新的 Json 写入问题

javascript - 从 YAML 生成 javascript 类/对象

python - 在Python中按数据帧的列中的每个值进行分组

Python垂直数组切片

python - 线程 QueueManagerThread 中的异常 - scikit-learn

python-3.x - CelebA 数据集无法使用 tfds.load() 访问

algorithm - 出于好奇 : How are serial numbers generated? 提示,算法?

python - 生成器函数性能