Search code examples
pythonpython-internalsreverse-iterator

What's the difference between a reversed tuple and a reversed list?


Reversing a tuple and reversing a list returns objects of different type:

>>> reversed((1,2))
<reversed at 0x7fffe802f748>
>>> reversed([1,2])
<list_reverseiterator at 0x7fffebdd4400>

They have the same dir. Neither type is a subclass of the other.

Why is that? What can one do that the other can't?


Solution

  • Basically, a list implements the __reversed__ method and returns an specialized object, while tuple falls back to the default implementation of reversed for any sequence:

    >>> list.__reversed__
    <method '__reversed__' of 'list' objects>
    >>> tuple.__reversed__
    AttributeError: type object 'tuple' has no attribute '__reversed__'
    

    Now, why list does not default to the sequence reversed object has to be found in the source code for the list object itself - probably it enables some optimizations by accessing directly some of internal list attributes.

    Actually looking at the C code, there is little difference, and certainly nothing that catches the eye -

    I'd dare say the special list __reversed__ implementation is a leftover from Python2 days where reversed would actually copy any other Python sequence to a list - so there would be no sense for other sequences to have special cases for it (and when they did implement the general enumreverse it was just good enough for tuples).

    I am pretty sure that if one would simply comment out the __reversed__ slot on listobject.c, Python and its lists would work as if nothing had happened, defaulting to the general case reversed.