关于python:yield 不起作用,但return起作用。

Yield does not work, but return does

本问题已经有最佳答案,请猛点这里访问。

我正在制作一个python irc bot。出于某种原因,join()方法中的yield语句会使它完全跳过该方法,但是如果我用一个返回值替换它,它就可以正常工作。但是,每次连接尝试失败时,我都需要产生一个错误。

我有一个bot的join方法,如果由于某种原因连接失败,它将返回服务器错误命令代码响应。如果bot成功加入,就没有了。

1
unsuccessful = bot.join(channels)

我可以做到:

1
2
3
if unsuccessful:
    for error in unsuccessful:
        print(error)

join方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
def join(self, channels):
    chan_errors = range(471, 480)  # See RFC for commands 471-479

    if isinstance(channels, str):
        channels = [channels,]

    for channel in channels:
        self.send('JOIN %s' % channel)
        for response in self.get_response('JOIN', chan_errors):  # Verify
            if response.command in chan_errors:
                channels.remove(channel)
                yield response
    self.channels.append(channels)

如果我将"yield response"与"return response"切换,它将运行该方法。

get-response方法看起来像

1
2
3
4
5
6
7
8
9
def get_response(self, commands, terminators=None):
    for msg in self.msg_gen():
        self.handle(msg)
        if msg.command in commands:
            if terminators is None:
                return msg
            yield msg
        if msg.command in terminators:
            return msg

它接收来自消息生成器的消息。这些命令是调用者正在查找的服务器命令,当找到终止符时,终止符将从生成器中退出。它有点像一个连体衣。

有人知道这里发生了什么吗?


通过在join方法中放入yield语句,您可以使它成为一个生成器。调用一个生成器方法只是创建一个生成器函数;您需要遍历它来获取数据。但是,由于生成器内部的执行在每次命中yield语句时都会停止,因此如果希望它完全运行,则需要耗尽它的所有内容。

您的代码就是这样运行的:

1
2
3
join_gen = bot.join(channels)
for error_msg in join_gen:
    print error_msg

python 2文档中的生成器

不过,我不确定发电机是否适合你。当您出现第一个错误时,返回response可能会更好,或者如果您想通过所有通道,将每个错误响应附加到一个错误列表中,并在完成后返回该列表。