Python 生成器表达式与产量

Python 生成器表达式与产量,python,generator,yield,generator-expression,Python,Generator,Yield,Generator Expression,我在看这段视频(),最后他谈到了生成器表达式如何与普通生成器的方式相同,但情况似乎并非如此,我读过的其他主题,生成器表达式与收益率之间没有区别。但是,从我所看到的情况来看,使用yield每次都会返回到for循环,而生成器表达式没有。它完成任务,然后返回for循环这可能是内存使用方面的一个相当大的差异(取决于您循环的内容),对吗?我的想法正确吗? # generators call yield which will return to the loop it's called in before

我在看这段视频(),最后他谈到了生成器表达式如何与普通生成器的方式相同,但情况似乎并非如此,我读过的其他主题,生成器表达式与收益率之间没有区别。但是,从我所看到的情况来看,使用yield每次都会返回到for循环,而生成器表达式没有。它完成任务,然后返回for循环这可能是内存使用方面的一个相当大的差异(取决于您循环的内容),对吗?我的想法正确吗?

# generators call yield which will return to the loop it's called in before coming back
def evens(stream):
    for n in stream:
        if n % 2 == 0:
            print("Inside evens")
            yield n

# this is the same as above just a generator expression
def evens2(stream):
    print("Inside evens2")
    return (n for n in stream if n % 2 == 0)

你的想法是错误的。生成器表达式与生成器函数的功能完全相同,只有一个区别:将
print()
调用放置在错误的位置。在
evens2
中,在执行生成器表达式之前打印,创建生成器对象,而在
evens
中,在生成器函数本身内部打印

如果这是Python 3(或者您使用了来自uuu future uuu导入打印u函数)的
,您也可以在生成器表达式中使用
print()
函数:

def evens2(stream):
    return (print('inside evens2') or n for n in stream if n % 2 == 0)
这相当于:

def evens(stream):
    for n in stream:
        if n % 2 == 0:
            yield print("Inside evens") or n
print()
始终返回
None
,因此
print(..)或n
将返回
n
。对其中一个进行迭代将打印并生成所有偶数
n

演示:


两者都使用
进行循环,
比较\u OP
以查看
二进制模的输出是否等于0,并且都使用
产生值
产生
n
的值

您的
print()
语句在
evens
中的位置错误。它应该在开始处,而不是在循环中。否则,生成器表达式和生成器函数的行为方式完全相同。只有在迭代.ty进行解释时,这两种方法才会产生
n
。我不确定我能不能在那里放一份打印声明。所以生成器表达式只是对我们隐藏yield语句。@user441521:正是这样,就像列表理解对我们隐藏
list.append()
调用一样。
>>> def evens2(stream):
...     return (print('inside evens2') or n for n in stream if n % 2 == 0)
...
>>> def evens(stream):
...     for n in stream:
...         if n % 2 == 0:
...             yield print("Inside evens") or n
...
>>> g1 = evens([1, 2, 3, 4, 5])
>>> g2 = evens2([1, 2, 3, 4, 5])
>>> g1
<generator object evens at 0x10bbf5938>
>>> g2
<generator object evens2.<locals>.<genexpr> at 0x10bbf5570>
>>> next(g1)
Inside evens
2
>>> next(g2)
inside evens2
2
>>> next(g1)
Inside evens
4
>>> next(g2)
inside evens2
4
>>> import dis
>>> dis.dis(compile('(n for n in stream if n % 2 == 0)', '', 'exec').co_consts[0])
  1           0 LOAD_FAST                0 (.0)
        >>    3 FOR_ITER                27 (to 33)
              6 STORE_FAST               1 (n)
              9 LOAD_FAST                1 (n)
             12 LOAD_CONST               0 (2)
             15 BINARY_MODULO
             16 LOAD_CONST               1 (0)
             19 COMPARE_OP               2 (==)
             22 POP_JUMP_IF_FALSE        3
             25 LOAD_FAST                1 (n)
             28 YIELD_VALUE
             29 POP_TOP
             30 JUMP_ABSOLUTE            3
        >>   33 LOAD_CONST               2 (None)
             36 RETURN_VALUE
>>> dis.dis(compile('''\
... def evens(stream):
...     for n in stream:
...         if n % 2 == 0:
...             yield n
... ''', '', 'exec').co_consts[0])
  2           0 SETUP_LOOP              35 (to 38)
              3 LOAD_FAST                0 (stream)
              6 GET_ITER
        >>    7 FOR_ITER                27 (to 37)
             10 STORE_FAST               1 (n)

  3          13 LOAD_FAST                1 (n)
             16 LOAD_CONST               1 (2)
             19 BINARY_MODULO
             20 LOAD_CONST               2 (0)
             23 COMPARE_OP               2 (==)
             26 POP_JUMP_IF_FALSE        7

  4          29 LOAD_FAST                1 (n)
             32 YIELD_VALUE
             33 POP_TOP
             34 JUMP_ABSOLUTE            7
        >>   37 POP_BLOCK
        >>   38 LOAD_CONST               0 (None)
             41 RETURN_VALUE