次のコードでは、なぜ 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
ベストアンサー1
これは、副作用のあるメソッドがx
存在する可能性があるためです。 はそれを 2 回呼び出しますが、 はそれを 1 回しか呼び出しません。__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__
1 回だけ呼び出すと、動作が変わる可能性があります。
定数が最初に乗算されるように演算の順序を変更する (または、コメントで述べたように、括弧を使用して定数をグループ化し、位置に関係なく一緒に演算されるようにする) ことで、折りたたみを実行することを明示的に指定することで、必要な最適化を実現できます。
>>> 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