Tail recursion to while iteration in 2 easy steps

Terry Reedy tjreedy at udel.edu
Wed Oct 2 22:41:00 EDT 2013


On 10/2/2013 9:46 PM, MRAB wrote:
> On 03/10/2013 02:39, Dave Angel wrote:
>> On 2/10/2013 21:24, Steven D'Aprano wrote:
>>
>>> On Wed, 02 Oct 2013 18:17:06 -0400, Terry Reedy wrote:
>>>
>>>> CPython core developers have be very conservative about what
>>>> tranformations they put into the compiler. (1,2,3) can always be
>>>> compiled as a constant, and so it is. [1,2,3] might or might not be a
>>>> constant, depending on the context, and no attempt is made to analyze
>>>> that.

To be specific: in

for i in [1,2,3]: print i

it looks like it might be save to pre-compile the list and just use it 
when the code is run. But if the above is in a function object whose 
code object is ever introspected, the list object could be accessed and 
mutated. Letting the compiler know that it can do the optimization is 
one reason to use tuples in situations like the above.

>>> The first sentence of this is correct. The next two don't quite make
>>> sense to me, since I don't understand what you mean by "constant" in
>>> this context.
 >>> I *think* you might be referring to the LOAD_CONST byte-code,

I am referring to constant-value objects included in the code object.
 >>> def f(): return (1,2,3)

 >>> f.__code__.co_consts
(None, 1, 2, 3, (1, 2, 3))

None is present as the default return, even if not needed for a 
particular function. Every literal is also tossed in, whether needed or not.

>>> which in Python 3.3 understands tuples like (1, 2, 3), but not lists.

The byte-code does not understand anything about types. LOAD_CONST n 
simply loads the (n+1)st object in .co_consts onto the top of the stack.

>>> S9 a literal (1, 2, 3) gets created at compile-time with a single
>>> LOAD_CONST call:
>>>
>>> py> from dis import dis
>>> py> dis(compile("x = (1, 2, 3)", '', 'exec'))
>>>   1           0 LOAD_CONST               4 ((1, 2, 3))
>>>               3 STORE_NAME               0 (x)
>>>               6 LOAD_CONST               3 (None)
>>>               9 RETURN_VALUE
>>>
>>>
>>> while a literal [1, 2, 3] does not:
>>>
>>
>> The difference is that a tuple can be reused, so it makes sense for the
>> comiler to produce it as a const.  (Much like the interning of small
>> integers)  The list, however, would always have to be copied from the
>> compile-time object.  So that object itself would be a phantom, used
>> only as the template with which the list is to be made.
>>
> The key point here is that the tuple is immutable, including its items.

The items of the tuple I gave as an examples are all constant. If they 
were not, the tuple would not be a constant for the purpose of 
compile-time creation.



-- 
Terry Jan Reedy




More information about the Python-list mailing list