这是一个很奇怪的问题,所以我会解释:
我有一个像这样的生成器,它充当IRC服务器的生成器前端:
def irc_iter(): # not the real code, simplified
msgs = get_msgs()
for msg in msgs:
if is_ping(msg):
pong()
else:
to_send = yield msg
for s in to_send:
send(s)
从理论上讲,这应该允许我做一些很酷的事情,例如:
server = connect()
for line in server:
if should_respond(line):
server.send('WOW SUCH MESSAGE')
但是,有一个障碍:generator.send
产生下一个值也是如此。这意味着server.send
还在给我下一条消息...我希望像其他所有消息一样处理,产生为line
。
我知道我可以通过接收发送后产生一个垃圾值来以丑陋的方式解决此问题,但是我试图使我的代码保持优雅,这是相反的。有没有一种方法可以告诉生成器我还不需要新值?
谢谢。
看来问题出在您每次迭代中两次调用生成器,一次是使用.send(None)
(在for循环中),一次是使用.send(response)
。
如果for循环可以在.send()而不是.next()上进行迭代,这将是一个简单的解决方法,但是我不熟悉任何无需包装即可使之工作的方法(pep342中的可选扩展continue语句?)。它在另一个生成器中(可能使用队列在.next()调用中将值推入.send())。不过,最简单的解决方案可能是:
server = connect()
response = None
try:
while True:
line = server.send(response)
response = None
if should_respond(line):
response ='WOW SUCH MESSAGE'
except StopIteration:
pass
我也刚遇到这个问题,也没有发现比虚拟yield
...更好的东西>
所以在您的生成器代码中:
# Input input_value = yield if input_value is None: # Handle situation if someone used your generator in a wrong way sys.exit(-1) yield "DUMMY YIELD JUST STOP HERE!!!"
并且在客户端代码中:
while True:
values = next(my_generator)
...
if values == 'INPUT_NEEDED':
# At this point you realize it's input time
next(my_generator) # Rewind to the input point
my_generator.send(12345) # Returns "DUMMY YIELD JUST STOP HERE!!!"
continue
# Continue the main loop