Surprised by the lack of constant folding
Chris Angelico
rosuav at gmail.com
Fri Mar 24 15:49:13 EDT 2017
On Sat, Mar 25, 2017 at 6:35 AM, Tim Chase
<python.list at tim.thechases.com> wrote:
> $ python3
> Python 3.4.2 (default, Oct 8 2014, 10:45:20)
> [GCC 4.9.1] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>>>> from dis import dis
>>>> def f(x):
> ... return x * 1024 * 1024
> ...
>>>> dis(f)
> 2 0 LOAD_FAST 0 (x)
> 3 LOAD_CONST 1 (1024)
> 6 BINARY_MULTIPLY
> 7 LOAD_CONST 1 (1024)
> 10 BINARY_MULTIPLY
> 11 RETURN_VALUE
>
> Is there any reason that Python doesn't do the constant folding of
> 1024 * 1024? Especially as it does constant folding if the order is
> reversed:
>
>>>> def f(x):
> ... return 1024 * 1024 * x
> ...
>>>> dis(f)
> 2 0 LOAD_CONST 2 (1048576)
> 3 LOAD_FAST 0 (x)
> 6 BINARY_MULTIPLY
> 7 RETURN_VALUE
>
>
> I'm cool with defining things as a constant and using those instead
> or front-loading my constants in my expressions, but the disparity
> struck me as a little odd. Any insights on the reasons/motivations
> for one and not the other?
The first example is:
(x * 1024) * 1024
The second is:
(1024 * 1024) * x
The first one can't be constant-folded without a semantic change
(Python can't know that x will always be a number, even if you do).
Suggestion: Use a different operator, which binds more tightly.
>>> def f(x):
... return x * 2**20
...
>>> dis(f)
2 0 LOAD_FAST 0 (x)
2 LOAD_CONST 3 (1048576)
4 BINARY_MULTIPLY
6 RETURN_VALUE
Since this evaluates as x * (2**20), it can be constant-folded.
ChrisA
More information about the Python-list
mailing list