为什么这个功能总是产生一个发电机?

时间:2016-10-06 04:17:26

标签: function python-3.x generator python-3.3

我对Python 3.3中的以下内容感到困惑:

>>> def foo(gen=False):
...     if not gen:
...         return list(range(10))
...     else:
...         for i in range(10):
...             yield i
... 
>>> foo()
<generator object foo at 0xb72a016c>
>>> foo(gen=False)
<generator object foo at 0xb72a0144>
>>> foo(gen=True)
<generator object foo at 0xb72a089c>
>>> 

我误解了什么?如果gen为False,则默认值为not genTrue[0,1,2,3,4,5,6,7,8,9],因此我应该得到一个整数列表True。另一方面,如果是(not gen) == False,则不应 scanf ("%s", a); 导致生成器?

2 个答案:

答案 0 :(得分:3)

在函数中包含yield使其成为生成器函数:当您执行函数时,您将获得一个生成器;没有其他执行发生。只有当生成器开始被要求输入元素时,函数本身才开始执行。

def not_a_generator():
    print(1)
    print(2)

not_a_generator()
# => 1
#    2

def is_a_generator():
    print(1)
    yield 7
    print(2)

is_a_generator()
# => <generator object bar at 0x10e1471a8>

list(is_a_generator())
# => 1
#    2
#    [7]

答案 1 :(得分:1)

yield语句放在if分支中并不重要。 documentation说:

  

在函数定义中使用yield足以使该定义创建生成器函数而不是正常函数。

但是,您可以通过简单地定义内部生成器函数来实现您的预​​期目标:

>>> def foo(gen=False):
...     if not gen:
...         return list(range(10))
...     else:
...         def foo():                 # the inner generator
...             for i in range(10):
...                 yield i
...         return foo()

>>> foo()    
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> foo(gen=False)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> foo(gen=True)
<generator object foo.<locals>.foo at 0x7f350c7563b8>
>>> g = foo(gen=True)
>>> next(g)
0

这一次,yield语句将内部foo转换为生成器。外foo仍然是正常函数。