产量与发电机表达 - 返回不同类型

时间:2013-05-27 20:56:00

标签: python generator yield

有这段代码:

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中测试的

4 个答案:

答案 0 :(得分:9)

很快在函数体中使用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一样,然后调用该函数会生成一个生成器对象。所以你可以在g()中调用f(),其结果与使用生成器表达式相同:

def f():
    return 3
    return g()

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

答案 1 :(得分:2)

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

相同
def f():
  return 3

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

答案 2 :(得分:1)

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))

答案 3 :(得分:0)

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