【问题标题】:Yield vs generator expression - different type returned产量与生成器表达式 - 返回不同的类型
【发布时间】:2013-05-22 17:43:41
【问题描述】:

有这个代码:

def f():
  return 3
  return (i for i in range(10))

x = f()
print(type(x)) # int

def g():
  return 3
  for i in range(10):
    yield i

y = g()
print(type(y)) # generator

当有返回生成器语句时,为什么f 返回int?我猜yield 和生成器表达式都返回生成器(至少在删除语句return 3 时),但是当有一次生成器表达式返回和第二次有yield 关键字时,还有其他一些函数编译规则里面?

这是在 Python 3.3 中测试的

【问题讨论】:

  • 你的 g() 方法不正确,你不能在同一个函数中混合 return 和 yield,你会得到一个错误。粘贴真实代码。
  • @LennartRegebro:事实上,您可以在同一个函数中混合收益和收益。在 Python 3.2 及更早版本中,您无法返回 (即 SyntaxError),但在 Python 3.3 及更高版本中,您甚至可以这样做。见Return in generator together with yield in Python 3.3
  • 啊,好吧,不知道。

标签: python generator yield


【解决方案1】:

当您在函数体中使用yield 语句时很快,它就变成了一个生成器。调用生成器函数只会返回该生成器对象。它不再是正常功能;生成器对象已接管控制权。

来自yield expression documentation

在函数定义中使用yield 表达式足以使该定义创建生成器函数而不是普通函数。

当调用生成器函数时,它会返回一个称为生成器的迭代器。然后该生成器控制生成器函数的执行。当调用生成器的方法之一时开始执行。

在常规函数中,调用该函数会立即将控制权切换到该函数体,您只是在测试函数的结果,由它的return 语句设置。在生成器函数中,return 仍然发出生成器函数结束的信号,但这会导致引发 StopIteration 异常。但是在调用 4 种生成器方法之一(.__next__().send().throw().close())之前,根本不会执行生成器函数体。

对于您的特定函数f(),您有一个常规函数,包含一个生成器。该函数本身并没有什么特别之处,只是它在执行return 3 时提前退出。下一行的生成器表达式独立存在,它不影响定义它的函数。您可以在没有函数的情况下定义它:

>>> (i for i in range(10))
<generator object <genexpr> at 0x101472730>

使用生成器表达式生成生成器对象,就像在函数中使用yield,然后调用该函数生成生成器对象。所以你可以在f() 中调用g(),结果与使用生成器表达式的结果相同:

def f():
    return 3
    return g()

g() 仍然是生成器函数,但在 f() 中使用它不会 使 f() 也成为生成器函数。只有yield 可以做到这一点。

【讨论】:

    【解决方案2】:
    def f():
      return 3
      return (i for i in range(10))
    

    一样
    def f():
      return 3
    

    第二个 return 语句永远不会被执行,只是在 f 中有一个生成器表达式不会使它成为一个生成器。

    【讨论】:

      【解决方案3】:
      def f():
        return 3
        #unreachable code below
        return (i for i in range(10))
      

      我相信你的意思是:

      def f():
        yield 3
        yield from (i for i in range(10))
      

      【讨论】:

        【解决方案4】:

        返回生成器不会使f 成为生成器函数。生成器只是一个对象,任何函数都可以返回生成器对象。如果您希望 f 成为生成器函数,则必须在函数内部使用 yield,就像使用 g 一样。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-29
          • 2018-05-02
          • 1970-01-01
          • 2016-05-30
          • 1970-01-01
          相关资源
          最近更新 更多