Почему 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 

2 Solutions collect form web for “Почему Python не оценивает арифметику с постоянными номерами до компиляции в байт-код?”

Это связано с тем, что 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 

Python оценивает выражения слева направо . Для f2() это означает, что сначала будет оценивать x*10 а затем умножить результат на 10. Попробуйте:

Пытаться:

 def f2(x): 10*10*x 

Это должно быть оптимизировано.

  • Почему python компилирует исходный код в байт-код перед интерпретацией?
  • Python - лучший язык программирования в мире.