为什么 Python 解包运算符适用于无序集合

Why does Python unpacking operator work with unordered collections

关于解包运算符 (*) 的 Python 3 tutorial 一般说的是 "list or tuple," 而错误消息表示使用不当需要 "sequence":

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 的 Built-in types 文档列出了以下序列类型:

快速测试:

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

请注意,集合类型(如 setfrozenset)和映射类型 (dict) 包含在此处。

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

我的问题:为什么所有可迭代类型(包括 setdict)都是不可压缩的? 它们不是序列类型,因为 [=上面的 28=] 表明它们应该是,并且在为位置参数解包时,无序行为会导致未定义的结果:

>>> 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

错误信息很可能是一个小错误*。在函数调用期间接受任何可迭代对象;这隐藏在 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.

(强调我的)

*正如@sytech 指出的那样,从 3.5.2 开始,它已在 Issue 4806 中得到修复,以对应参考手册中的正确措辞。

在(至少)Python 3.5.2 中不再是这种情况 -- 可能被认为是一个问题并在比您使用的版本晚的版本中进行了更改。该消息现在更恰当地读取 iterable 而不是 sequence

https://bugs.python.org/issue4806

>>> def foo(*args):
...     print(*args)
...
>>> foo(*1)
TypeError: foo() argument after * must be an iterable, not int