5

有这个代码:

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

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

这是在 Python 3.3 中测试的

4

4 回答 4

10

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

yield表达式文档

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

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

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

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

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

使用生成器表达式会生成生成器对象,就像yield在函数中使用一样,然后调用该函数会生成生成器对象。因此,您可以调用g()f()使用生成器表达式相同的结果:

def f():
    return 3
    return g()

g()仍然是生成器函数,但在其中使用它f()不会生成f()生成器函数。只能yield这样做。

于 2013-05-27T20:57:37.533 回答
3
def f():
  return 3
  return (i for i in range(10))

是相同的

def f():
  return 3

第二个 return 语句永远不会被执行,只是通过在其中包含一个生成器表达式f 并不使其成为一个生成器。

于 2013-05-27T20:57:44.287 回答
2
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))
于 2013-05-27T20:58:21.127 回答
0

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

于 2013-05-27T20:59:09.400 回答