bla*_*air 6 python generator yield-keyword python-3.x
我试图通过构建一个生成器来理解yield语句的行为,该生成器的行为与“枚举”内置函数类似,但我发现根据我如何迭代它而出现不一致。
def enumerate(sequence, start=0):
n = start
for elem in sequence:
print("Before the 'yield' statement in the generator, n = {}".format(n))
yield n, elem
n += 1
print("After the 'yield' statement in the generator, n = {}".format(n))
Run Code Online (Sandbox Code Playgroud)
我对生成器的理解是,一旦到达yield 语句,代码的执行就会停止,并返回一个值。这与我通过下面的脚本得到的结果相匹配。
a = 'foo'
b = enumerate(a)
n1,v1 = next(b)
print('n1 = {}, v1 = {}\n'.format(n1,v1))
n2,v2 = next(b)
print('n2 = {}, v2 = {}'.format(n2,v2))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,生成器似乎完全停止在yield语句处,并在n+=1处用第二个“next”语句恢复:
Before the 'yield' statement in the generator, n = 0
n1 = 0, v1 = f
After the 'yield' statement in the generator, n = 1
Before the 'yield' statement in the generator, n = 1
n2 = 1, v2 = o
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用下面的 for 循环,生成器似乎不会在yield 语句处停止。
for n,v in enumerate(a[0:1]):
print('n = {}, v = {}'.format(n,v))
Run Code Online (Sandbox Code Playgroud)
这就是我得到的:
Before the 'yield' statement in the generator, n = 0
n = 0, v = f
After the 'yield' statement in the generator, n = 1
Run Code Online (Sandbox Code Playgroud)
考虑评论进行编辑
我意识到我只迭代了一个元素,但我没想到会看到最后一个“在生成器中的‘yield’语句之后”句子(即使我迭代所有元素,它也会出现。
print('\n\n')
for n,v in enumerate(a):
print('n = {}, v = {}'.format(n,v))
Before the 'yield' statement in the generator, n = 0
n = 0, v = f
After the 'yield' statement in the generator, n = 1
Before the 'yield' statement in the generator, n = 1
n = 1, v = o
After the 'yield' statement in the generator, n = 2
Before the 'yield' statement in the generator, n = 2
n = 2, v = o
After the 'yield' statement in the generator, n = 3
Run Code Online (Sandbox Code Playgroud)
为什么会出现这种情况?
这里的根本问题是,您混淆了仅通过查看生成器就知道何时会耗尽的事实与Python 只能通过运行代码来知道的事实。当Python到达yield
你认为是最后一个的时候,它实际上并不知道它是最后一个。如果你的生成器看起来像这样怎么办:
def enumeratex(x, start=0):
for elem in x:
yield start, x
start += 1
yield start, None
Run Code Online (Sandbox Code Playgroud)
在这里,出于无人知晓的原因,最终None
元素在主生成器循环之后返回。Python 无法知道生成器已经完成,除非你
在 Python 3.7 之前的版本中,生成器可以引发StopIteration
以指示终止。事实上, return 语句相当于raise StopIteration
(如果返回None
) 或raise StopIteration(return_value)
。
因此,虽然告诉 Python 结束生成器的确切方式取决于您,但您必须明确说明这一点。Ayield
本身并不结束生成器。
长话短说
生成器中循环中的所有代码都将始终运行,即使在生成最后一个值之后也是如此,因为 Python 只能通过实际执行所有代码才能知道它是最后一个值。
归档时间: |
|
查看次数: |
5921 次 |
最近记录: |