pythonpython-3.xlisttuplessplat

Why does splatting create a tuple on the rhs but a list on the lhs?


Consider, for example,

squares = *map((2).__rpow__, range(5)),
squares
# (0, 1, 4, 9, 16)

*squares, = map((2).__rpow__, range(5))
squares
# [0, 1, 4, 9, 16]

So, all else being equal we get a list when splatting on the lhs and a tuple when splatting on the rhs.

Why?

Is this by design, and if yes, what's the rationale? Or, if not, are there any technical reasons? Or is this just how it is, no particular reason?


Solution

  • The fact that you get a tuple on the RHS has nothing to do with the splat. The splat just unpacks your map iterator. What you unpack it into is decided by the fact that you've used tuple syntax:

    *whatever,
    

    instead of list syntax:

    [*whatever]
    

    or set syntax:

    {*whatever}
    

    You could have gotten a list or a set. You just told Python to make a tuple.


    On the LHS, a splatted assignment target always produces a list. It doesn't matter whether you use "tuple-style"

    *target, = whatever
    

    or "list-style"

    [*target] = whatever
    

    syntax for the target list. The syntax looks a lot like the syntax for creating a list or tuple, but target list syntax is an entirely different thing.

    The syntax you're using on the left was introduced in PEP 3132, to support use cases like

    first, *rest = iterable
    

    In an unpacking assignment, elements of an iterable are assigned to unstarred targets by position, and if there's a starred target, any extras are stuffed into a list and assigned to that target. A list was chosen instead of a tuple to make further processing easier. Since you have only a starred target in your example, all items go in the "extras" list assigned to that target.