brianpck brianpck - 1 month ago 9
Python Question

Why does Python unpacking operator work with unordered collections

The Python 3 tutorial about the unpacking operator (

*
) generically speaks of a "list or tuple," while the error message for improper use says that a "sequence" is needed:

Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> def f(a, b):
... return a / b
...
>>> f(*1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() argument after * must be a sequence, not int


Python 3's Built-in types documentation lists the following sequence types:


  • Sequence Types —
    list
    ,
    tuple
    ,
    range

  • Text Sequence Type —
    str

  • Binary Sequence Types —
    bytes
    ,
    bytearray
    ,
    memoryview



Quick test:

>>> all(isinstance(x, collections.Sequence) for x in [[], (), range(1), '', b''])
True


Note that set types (like
set
and
frozenset
) and mapping types (
dict
) are not included here.

>>> any(isinstance(x, collections.Sequence) for x in [set(), {}])
False





My question: Why are all iterable types (including a
set
or
dict
) unpackable?
They are not sequence types, as the
TypeError
above suggests they should be, and unordered behavior leads to undefined results when unpacking for positional args:

>>> def f(a, b):
... return a / b
...
>>> f(*{4, 2})
0.5
>>> f(*{8, 2})
4.0
>>> f(*{4:1, 2:1})
0.5
>>> f(*{2:1, 8:1})
4.0

Answer

The error message is most likely a little bug*. Anything that is an iterable is accepted during function calls; this is hidden inside the section for Calls in the Python Reference Manual:

If the syntax *expression appears in the function call, expression must evaluate to an iterable. Elements from these iterables are treated as if they were additional positional arguments.

(Emphasis mine)

*Which, as of 3.5.2 as @sytech pointed out, was fixed in Issue 4806 to correspond to the correct wording in the reference manual.

Comments