【问题标题】:Yield does not work, but return does [duplicate]产量不起作用,但回报确实[重复]
【发布时间】:2013-10-25 03:57:32
【问题描述】:

我正在制作一个 Python irc 机器人。出于某种原因,我的 join() 方法中的 yield 语句使它完全跳过了该方法,但是如果我用 return 替换它,它就可以正常工作。但是,每次不成功的加入尝试都需要产生一个错误。

我有一个 bot 的 join 方法,如果由于某种原因连接不成功,它会返回服务器错误命令代码响应。如果 bot 成功加入,则为 None。

unsuccessful = bot.join(channels)

我能做到:

if unsuccessful:
    for error in unsuccessful:
        print(error)

join方法是这样的

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 方法看起来像

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

它从消息生成器接收消息。这些命令是调用者正在寻找的服务器命令,当找到终止符时,终止符会从生成器中退出。这有点像协程。

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

【问题讨论】:

  • 你了解yield 是什么以及如何使用生成器吗? bot.join(channels) 返回一个生成器;您需要对其进行迭代以获得它产生的值。
  • @BrenBarn 我将编辑问题以说明我将使用“不成功”作为生成器
  • 以什么方式“不工作”?它有什么作用?你是说它不会在循环中打印任何东西?
  • 它根本不进入 join() 方法,而是运行下一个方法调用。没有例外或任何东西。
  • 在您开始迭代 unsuccessful 之前,它不会进入 join 方法。这就是生成器的工作原理。

标签: python irc


【解决方案1】:

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

这样你的代码会一直运行:

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

Generators in the Python 2 docs

不过,我不确定生成器是否适合您。当您遇到第一个错误时返回response 可能会更好,或者如果您想遍历所有渠道,请将每个错误响应附加到错误列表并在完成后返回该列表。

【讨论】:

  • 好的,如果无论如何我都无法让它工作,我会选择后者。否则我会毫无意义地遍历无。这就像回到 Java 或其他语言并不得不返回一个数组。我很惊讶我在其他地方找不到这个。我认为生成器在迭代时会添加到变量中。现在这是有道理的。
  • Mark Hildreth 发布的链接The Python yield keyword explained 是 Python 生成器最好的(如果不是最好的!)资源之一 - 比 pydocs 好得多! e-satis 只是杀死它:D
猜你喜欢
  • 1970-01-01
  • 2017-03-08
  • 2016-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2013-06-28
相关资源
最近更新 更多