Inspired by this question about Python caching small integers.
Is it possible for the Python compiler to replace (0 - 6) with -6 at compile time? The code below suggests that it does not. If it is not possible, why not? I don't think that the meaning of 0
, -
, or 6
can be different at run time.
If this is possible, why does CPython not do it?
# test_integers.py
def test_integers():
print "-6 is -6 ?", -6 is -6 # True
print "(0 - 6) is -6 ?", (0 - 6) is -6 # False
# import_test_integers.py
import test_integers
test_integers.test_integers()
My Python details in case this is very implementation-dependent:
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
First, you shouldn't be using is
to compare integer values to detect optimizations. That has nothing to do with anything, as explained in the question you linked. If you want to know what optimizations were performed on your function, use the dis module, which produces (in 2.7.2):
>>> import dis
>>>
>>> def test_integers():
... print "-6 is -6 ?", -6 is -6 # True
... print "(0-6) is -6 ?", (0 - 6) is -6 # False
...
>>> dis.dis(test_integers)
2 0 LOAD_CONST 1 ('-6 is -6 ?')
3 PRINT_ITEM
4 LOAD_CONST 2 (-6)
7 LOAD_CONST 2 (-6)
10 COMPARE_OP 8 (is)
13 PRINT_ITEM
14 PRINT_NEWLINE
3 15 LOAD_CONST 3 ('(0-6) is -6 ?')
18 PRINT_ITEM
19 LOAD_CONST 6 (-6)
22 LOAD_CONST 2 (-6)
25 COMPARE_OP 8 (is)
28 PRINT_ITEM
29 PRINT_NEWLINE
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
and you see that the subtraction actually was optimized away. You can see some others, too:
>>> def f():
... x = 1+2
... x = 2-3
... x = 3*4
... x = 4/5
... x = 5**6
...
>>> dis.dis(f)
2 0 LOAD_CONST 7 (3)
3 STORE_FAST 0 (x)
3 6 LOAD_CONST 8 (-1)
9 STORE_FAST 0 (x)
4 12 LOAD_CONST 9 (12)
15 STORE_FAST 0 (x)
5 18 LOAD_CONST 4 (4)
21 LOAD_CONST 5 (5)
24 BINARY_DIVIDE
25 STORE_FAST 0 (x)
6 28 LOAD_CONST 10 (15625)
31 STORE_FAST 0 (x)
34 LOAD_CONST 0 (None)
37 RETURN_VALUE