在 Python 中使用带有 While 循环的生成器
Using a Generator with a While loop in Python
我希望能够做这样的事情:
while next(gen):
print(value_from_gen)
我从这个列表开始
x=[1,2,3,4,5]
然后我为 return 值
创建一个生成器
g = ({i:i*2} for i in x
)
当我尝试时:
while val = next(g):
print(val)
我得到:
File "main.py", line 6
while val = next(g):
^
SyntaxError: invalid syntax
当我尝试时:
while next(g):
print(next())
它跳过了一些值,我得到了错误:
{2: 4}
{4: 8}
Traceback (most recent call last):
File "main.py", line 7, in <module>
print(next(g))
StopIteration
当我尝试时:
v= -1
while v is not None:
v=next(g)
print(v)
我得到了所有的值,但仍然得到错误:
{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10}
Traceback (most recent call last):
File "main.py", line 8, in <module>
v=next(g)
StopIteration
当我尝试时:
for v in g:
print(v)
我得到正确的结果:
{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10}
但是,我想知道这是否等同于调用 next(g)
并且它是否保留了生成器的惰性优势?
另外我想知道是否不可能用实际的 while 循环 来做到这一点?
记得赋值表达式(:=)是在Python3.8
中引入的
你不用显式调用next()
,for循环就是你想要的,它确实保持了生成器的惰性。
用while循环实现,我觉得应该用try/except StopIteration
,但是没有意义,就用for循环,
forloop 版本保留了生成器的惰性,这将是实现您在这个问题中提出的问题的 pythonic 版本。
如果您想尝试将其强制进入 while 循环,您可以这样做
try:
element = next(g)
while True:
print(element)
except StopIteration:
pass
如果您不喜欢 try/except 您可以在下次调用时使用默认值
element = next(g, None)
while element is not None:
print(element)
但是,如果 None
是您的生成器中的有效条目,这将中断。您必须使用一些不能出现在您的生成器序列中的默认值。
x = [1, 2, 3, 4, 5]
g = ({i: i*2} for i in x)
当生成器中没有要迭代的元素时引发 StopIteration 异常。
您可能打算使用 Walrus Assignment check here
try:
while val := next(g): # walurs assignment added in Python3.8
print(val)
except StopIteration:
# StopIteration exception raised when no element left in generator to iterate over
pass
next()
被调用两次
try:
# This is totaly invalid syntax, because `next()` being call twise so you will have alternate number printed in console
while next(g):
#print(next()) # incorrect syntax
print(next(g)) # correct syntax but `next()`calling twice
except StopIteration:
pass
这是正确的,但您只需要应用异常处理。另外,最好使用 @Bard 提到的 pythonic 方式
try:
v = -1
while v is not None:
v = next(g)
print(v)
except StopIteration:
pass
也基于, you may pass False
to default parameter of next
函数:
while element:= next(g, False):
print(element)
我希望能够做这样的事情:
while next(gen):
print(value_from_gen)
我从这个列表开始
x=[1,2,3,4,5]
然后我为 return 值
创建一个生成器
g = ({i:i*2} for i in x
)
当我尝试时:
while val = next(g):
print(val)
我得到:
File "main.py", line 6
while val = next(g):
^
SyntaxError: invalid syntax
当我尝试时:
while next(g):
print(next())
它跳过了一些值,我得到了错误:
{2: 4}
{4: 8}
Traceback (most recent call last):
File "main.py", line 7, in <module>
print(next(g))
StopIteration
当我尝试时:
v= -1
while v is not None:
v=next(g)
print(v)
我得到了所有的值,但仍然得到错误:
{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10}
Traceback (most recent call last):
File "main.py", line 8, in <module>
v=next(g)
StopIteration
当我尝试时:
for v in g:
print(v)
我得到正确的结果:
{1: 2}
{2: 4}
{3: 6}
{4: 8}
{5: 10}
但是,我想知道这是否等同于调用 next(g)
并且它是否保留了生成器的惰性优势?
另外我想知道是否不可能用实际的 while 循环 来做到这一点?
记得赋值表达式(:=)是在Python3.8
中引入的你不用显式调用
next()
,for循环就是你想要的,它确实保持了生成器的惰性。用while循环实现,我觉得应该用
try/except StopIteration
,但是没有意义,就用for循环,
forloop 版本保留了生成器的惰性,这将是实现您在这个问题中提出的问题的 pythonic 版本。
如果您想尝试将其强制进入 while 循环,您可以这样做
try:
element = next(g)
while True:
print(element)
except StopIteration:
pass
如果您不喜欢 try/except 您可以在下次调用时使用默认值
element = next(g, None)
while element is not None:
print(element)
但是,如果 None
是您的生成器中的有效条目,这将中断。您必须使用一些不能出现在您的生成器序列中的默认值。
x = [1, 2, 3, 4, 5]
g = ({i: i*2} for i in x)
当生成器中没有要迭代的元素时引发 StopIteration 异常。 您可能打算使用 Walrus Assignment check here
try:
while val := next(g): # walurs assignment added in Python3.8
print(val)
except StopIteration:
# StopIteration exception raised when no element left in generator to iterate over
pass
next()
被调用两次
try:
# This is totaly invalid syntax, because `next()` being call twise so you will have alternate number printed in console
while next(g):
#print(next()) # incorrect syntax
print(next(g)) # correct syntax but `next()`calling twice
except StopIteration:
pass
这是正确的,但您只需要应用异常处理。另外,最好使用 @Bard 提到的 pythonic 方式
try:
v = -1
while v is not None:
v = next(g)
print(v)
except StopIteration:
pass
也基于False
to default parameter of next
函数:
while element:= next(g, False):
print(element)