4

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
brianpck
  • 8,084
  • 1
  • 22
  • 33
  • Pretty sure only iterator methods are required for that. Unpacking predates abstract collection types. –  Oct 28 '16 at 16:10
  • 2
    The error message in Python 3.5 is `TypeError: foo() argument after * must be an iterable, not int` – sytech Oct 28 '16 at 16:15
  • 1
    So, basically you ask [Why is the order in dictionaries and sets arbitrary?](http://stackoverflow.com/questions/15479928/why-is-the-order-in-dictionaries-and-sets-arbitrary) – Łukasz Rogalski Oct 28 '16 at 16:20
  • 1
    @ŁukaszRogalski No--my question is why unordered collections allow unpacking, given the error message and unexpected behavior with positional args. I understand that they are arbitrary. – brianpck Oct 28 '16 at 16:21
  • Dict and set are not a sequences, but they are iterables (they implement iterator protocol). Since they are implementing it, there is absolutely no reason for them not to be able to unpack. Integers are not iterables, why would you expect them to unpack successfully? – Łukasz Rogalski Oct 28 '16 at 16:21
  • @ŁukaszRogalski I think you're misunderstanding OP's question. His question is asking why the raised TypeError uses the term "sequence" and not "iterable" – sytech Oct 28 '16 at 16:22
  • @ŁukaszRogalski Right: as it turns out, there is a bug in the error description I cited which was corrected in a future release. – brianpck Oct 28 '16 at 16:22
  • 1
    I guess the issue with the error message is "solved", but something still doesn't feel completely right about being able to unpack *positional* arguments from an *unordered* collection. (No doubt this is why the error message originally mentioned *sequences*; as that would, at least naively, make the most sense. And maybe it was even true in very early versions of Python.) – John Y Oct 31 '16 at 22:50

2 Answers2

4

This is no longer the case in (at least) Python 3.5.2 -- Probably was recognized as an issue and changed in a version later than what you're using. The message now more appropriately reads iterable instead of sequence

See https://bugs.python.org/issue4806

>>> def foo(*args):
...     print(*args)
...
>>> foo(*1)
TypeError: foo() argument after * must be an iterable, not int
sytech
  • 29,298
  • 3
  • 45
  • 86
2

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.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253