两者之间只有细微的差别。您可以使用该
dis模块自己检查这种事情。
编辑: 我的第一个版本反编译了在交互式提示符下在module-
scope上创建的生成器表达式。这与在函数内部使用的OP版本略有不同。我已对此进行了修改,以匹配问题中的实际情况。
如下所示,“ yield”生成器(第一种情况)在设置中具有三个额外的指令,但与第一个指令相比,
FOR_ITER它们仅在一个方面有所不同:“
yield”方法在循环内部使用
LOAD_FAST代替
LOAD_DEREF。的
LOAD_DEREF是“而较慢的”比
LOAD_FAST,所以它使得“产量”版本略快于对的足够大的值的生成器表达式
x(外环),因为该值
y是稍快于每遍加载。对于较小的值,
x由于设置代码的额外开销,它会稍微慢一些。
值得指出的是,生成器表达式通常将在代码中内联使用,而不是将其与此类函数包装在一起。这将消除一些设置开销,并使生成器表达式对于较小的循环值稍快一些,即使在其他情况下
LOAD_FAST给“
yield”版本带来了好处。
在任何一种情况下,性能差异都不足以证明在一个或另一个之间做出决定是合理的。可读性的重要性要大得多,因此请使用对当前情况最易读的方式。
>>> def Generator(x, y):... for i in xrange(x):... for j in xrange(y):... yield(i, j)...>>> dis.dis(Generator) 20 SETUP_LOOP 54 (to 57) 3 LOAD_GLOBAL 0 (xrange) 6 LOAD_FAST 0 (x) 9 CALL_FUNCTION 1 12 GET_ITER >> 13 FOR_ITER 40 (to 56) 16 STORE_FAST 2 (i) 3 19 SETUP_LOOP 31 (to 53) 22 LOAD_GLOBAL 0 (xrange) 25 LOAD_FAST 1 (y) 28 CALL_FUNCTION 1 31 GET_ITER >> 32 FOR_ITER 17 (to 52) 35 STORE_FAST 3 (j) 4 38 LOAD_FAST 2 (i) 41 LOAD_FAST 3 (j) 44 BUILD_TUPLE 2 47 YIELD_VALUE 48 POP_TOP 49 JUMP_ABSOLUTE32 >> 52 POP_BLOCK >> 53 JUMP_ABSOLUTE13 >> 56 POP_BLOCK >> 57 LOAD_ConST 0 (None) 60 RETURN_VALUE>>> def Generator_expr(x, y):... return ((i, j) for i in xrange(x) for j in xrange(y))...>>> dis.dis(Generator_expr.func_pre.co_consts[1]) 20 SETUP_LOOP 47 (to 50) 3 LOAD_FAST 0 (.0) >> 6 FOR_ITER 40 (to 49) 9 STORE_FAST 1 (i) 12 SETUP_LOOP 31 (to 46) 15 LOAD_GLOBAL 0 (xrange) 18 LOAD_DEREF 0 (y) 21 CALL_FUNCTION 1 24 GET_ITER >> 25 FOR_ITER 17 (to 45) 28 STORE_FAST 2 (j) 31 LOAD_FAST 1 (i) 34 LOAD_FAST 2 (j) 37 BUILD_TUPLE 2 40 YIELD_VALUE 41 POP_TOP 42 JUMP_ABSOLUTE25 >> 45 POP_BLOCK >> 46 JUMP_ABSOLUTE 6 >> 49 POP_BLOCK >> 50 LOAD_ConST 0 (None) 53 RETURN_VALUE



