Python はバイトコードにコンパイルする前に定数演算を評価しないのはなぜですか? 質問する

Python はバイトコードにコンパイルする前に定数演算を評価しないのはなぜですか? 質問する

次のコードでは、なぜ 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 

おすすめ記事