当标志设置为False
时,我试图使列表暂时无法读取。也就是说,当标志为False
时读取列表没有给出任何值(就好像它是空的或列表已经用完)。一旦它回到True
,列表就会再次变为可读,并且光标从最后停止的位置继续。我当前的实现继续读取,但不记得光标以前的位置。有谁知道如何改变它?我知道我可以有一个变量来跟踪光标的位置,但是有更优雅的方式吗?
items = range(0, 5)
flag = True
def values():
for v in items:
while not flag:
yield None
yield v
def read():
for i in values():
if i is None:
return
yield i
def run():
global flag
# should print just 0 1 2, as flag is False when i == 2
for i in read():
if i == 2:
flag = False
print i
print "flip!"
# should print just 3 4, as the previous cursor position should be used
flag = True
for i in read():
print i
run() # outputs 0 1 2 flip 0 1 2 3 4 rather than the expected 0 1 2 flip 3 4
答案 0 :(得分:2)
您的第一个循环正常,您可以在第一个print "**********"
循环后添加for
来查看结果。
但是对于第二个循环,你有一个错误的理解,因为在第二个循环中你不能从你转换falg
到False
的那个部分迭代你的列表!第二个循环将从开始开始,因此您可以将第一个循环中最后一个元素的索引保存到indx
变量并将其传递给您的函数:
items = range(0, 5)
flag = True
def values(indx):
for v in items[indx:]:
while not flag:
yield None
yield v
def read(indx=0):
for i in values(indx):
if i is None:
return
yield i
def run():
global flag
global indx
# should print just 0 1 2
for i,j in enumerate(read(),1):
if j == 2:
flag = False
indx=i
print j
print "**********"
# should print just 3 4
flag = True
for i in read(indx):
print i
print '********'
run()
结果:
0
1
2
**********
3
4
********
答案 1 :(得分:1)
你不能用发电机做你想做的事;生成器是专门的迭代器,迭代器只能通过迭代一次。一旦他们筋疲力尽(StopIterator
已被提出),他们就不能产生更多的物品。
另一方面,您的代码需要引发StopIteration
(第一个循环结束),然后第二个循环继续再次迭代。
而不是在生成器中处理它,只是停止迭代。创建生成器一次,然后在两个循环中使用它:
def run():
iterator = read()
for i in iterator:
print i
if i == 2:
break # stop iterating
print 'flip'
# resume iterating
for i in iterator:
print i
答案 2 :(得分:1)
这样做会从根本上打破according the Python's iterator protocol:
协议的目的是一旦迭代器的next()方法引发StopIteration,它将继续在后续调用中这样做。不遵守此属性的实现被视为已损坏。
你应该做的是将它作为一个类并将索引存储为实例变量。这样您就不必传入参数或依赖全局变量。
答案 3 :(得分:0)
您可能会在下面找到感兴趣的发电机。使用生成器的send()
方法,我们可以将数据发送回生成器。有关此功能的详细信息,请参阅Python文档中的Yield expressions。 (该文档的Python 3版本为here)。
#!/usr/bin/env python
def latched_iter(iterable):
''' Yield items from iterable only when latch is True '''
latch = False
while True:
latch = yield iterable.next() if latch else None
def main():
gen = latched_iter(iter('abcdefghijklmnop'))
gen.send(None)
for i in xrange(25):
try:
val = gen.send(i < 5 or i >= 10)
except StopIteration:
break
print i, val
if __name__ == '__main__':
main()
<强>输出强>
0 a
1 b
2 c
3 d
4 e
5 None
6 None
7 None
8 None
9 None
10 f
11 g
12 h
13 i
14 j
15 k
16 l
17 m
18 n
19 o
20 p