On 10/2/2013 10:34 PM, Steven D'Aprano wrote:
You are both assuming that LOAD_CONST will re-use the same tuple
(1, 2, 3) in multiple places.
No I did not. To save tuple creation time, a pre-compiled tuple is
reused when its display expression is re-executed. If I had been
interested in multiple occurrences of the same display, I would have tested.
>>> def f():
a = 1,'a',3333, 'bbb'; x = 1,'a',3333, 'bbb'
b = 1,'a',3333, 'bbb'
c = 'a'
d = 3333 + 3333
>>> f.__code__.co_consts
(None, 1, 'a', 3333, 'bbb', (1, 'a', 3333, 'bbb'), (1, 'a', 3333,
'bbb'), (1, 'a', 3333, 'bbb'), 6666)
Empirically, ints and strings are checked for prior occurrence in
co_consts before being added. I suspect None is too, but will not assume.
How is the issue of multiple occurrences of constants relevant to my
topic statement? Let me quote it, with misspellings corrected.
"CPython core developers have been very conservative about what
transformations they put into the compiler." [misspellings corrected]
Aha! Your example and that above reinforce this statement. Equal tuples
are not necessarily identical and cannot necessarily be substituted for
each other in all code.
>>> (1, 2) == (1.0, 2.0)
True
But replacing (1.0, 2.0) with (1, 2), by only storing the latter, would
not be valid without some possibly tricky context analysis. The same is
true for equal numbers, and the optimizer pays attention.
>>> def g():
a = 1
b = 1.0
>>> g.__code__.co_consts
(None, 1, 1.0)
For numbers, the proper check is relatively easy:
for item in const_list:
if type(x) is type(item) and x == item:
break # identical item already in working list
else:
const_list.append(x)
Writing a valid recursive function to do the same for tuples, and
proving its validity to enough other core developers to make it
accepted, is much harder and hardly seems worthwhile.
It would probably be easier to compare the parsed AST subtrees for the
displays rather than the objects created from them.
---
> py> def f():
> ... a = (1, 2, 3)
> ... b = (1, 2, 3)
[snip]
> So even though both a and b are created by the same LOAD_CONST
byte-code,
I am not sure what you mean by 'created'. LOAD_CONST puts the address of
an object in co_consts on the top of the virtual machine stack.
> the object is not re-used (although it could be!)
It can be reused, in this case, because the constant displays are
identical, as defined above.
> and two distinct tuples are created.
Because it is not easy to make the compiler see that only one is needed.
--
Terry Jan Reedy
--
https://mail.python.org/mailman/listinfo/python-list