我有以下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/