在下面的代码中,为什么Python不将f2
编译为与f1
相同的字节码?
有没有理由不这样做?
>>> def f1(x):
x*100
>>> dis.dis(f1)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (100)
6 BINARY_MULTIPLY
7 POP_TOP
8 LOAD_CONST 0 (None)
11 RETURN_VALUE
>>> def f2(x):
x*10*10
>>> dis.dis(f2)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (10)
6 BINARY_MULTIPLY
7 LOAD_CONST 1 (10)
10 BINARY_MULTIPLY
11 POP_TOP
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
答案 0 :(得分:71)
这是因为x
可能有一个带有副作用的__mul__
方法。 x * 10 * 10
两次调用__mul__
,而x * 100
只调用一次:
>>> class Foo(object):
... def __init__ (self):
... self.val = 5
... def __mul__ (self, other):
... print "Called __mul__: %s" % (other)
... self.val = self.val * other
... return self
...
>>> a = Foo()
>>> a * 10 * 10
Called __mul__: 10
Called __mul__: 10
<__main__.Foo object at 0x1017c4990>
自动折叠常量,只调用__mul__
一次就可以改变行为。
您可以通过重新排序操作来获得所需的优化,以便首先将常数相乘(或者,如注释中所述,使用括号将它们分组,使得它们仅在一起操作,无论位置如何),因此明确表达你对折叠的渴望:
>>> def f1(x):
... return 10 * 10 * x
...
>>> dis.dis(f1)
2 0 LOAD_CONST 2 (100)
3 LOAD_FAST 0 (x)
6 BINARY_MULTIPLY
7 RETURN_VALUE
答案 1 :(得分:17)