为啥解包在 Python 中给出一个列表而不是一个元组?

Posted

技术标签:

【中文标题】为啥解包在 Python 中给出一个列表而不是一个元组?【英文标题】:Why does unpacking give a list instead of a tuple in Python?为什么解包在 Python 中给出一个列表而不是一个元组? 【发布时间】:2020-08-09 05:36:09 【问题描述】:

这对我来说真的很奇怪,因为默认情况下我认为解包会产生元组。

就我而言,我想使用 prefix 键进行缓存,因此首选元组。

# The r.h.s is a tuple, equivalent to (True, True, 100)
*prefix, seed = ml_logger.get_parameters("Args.attn", "Args.memory_gate", "Args.seed")
assert type(prefix) is list

但我认为解包会返回一个元组。

这里是相关的 PEP:https://www.python.org/dev/peps/pep-3132/

-- 更新--

鉴于下面的评论和答案,特别是我希望解包给出一个元组,因为在函数参数中,展开 arg 始终是一个元组而不是一个列表。

正如 Jason 所指出的,在解包过程中,无法提前知道结果的长度,因此在实现方面,包罗万象必须从动态附加列表开始。将其转换为列表在大多数情况下都是浪费精力。

从语义上讲,我希望有一个元组来保持一致性。

【问题讨论】:

在您链接到的那个 PEP 中:“这个 PEP 提议对可迭代的解包语法进行更改,允许指定一个“包罗万象”的名称,该名称将被分配一个 list未分配给“常规”名称的所有项目。” 包罗万象的几乎必须是一个列表:没有通用的方法来预测它将有多大(例如,RHS 可能类似于生成器),但是元组具有完全指定要创建的确切大小。因此,将项目收集到列表中是唯一实际的选择。 (该列表之后可能已隐式转换为元组 - 这在您的情况下会很好,但在实际需要列表的情况下不太好,并且在大多数类型不需要的情况下完全浪费精力问题。) @jasonharper 感谢您的评论!这有助于澄清当前模式背后的原因。 IMO 这似乎是来自实施/效率方面的一个漏洞,它下降了一级。在语义层面上,这些都不是问题。 【参考方案1】:

这个问题是mentioned in that PEP (PEP 3132):

在对 python-3000 列表[1] 进行简短讨论后,Guido 以当前形式接受了 PEP。讨论的可能变化是:[...]

尝试为加星标的目标赋予与源可迭代对象相同的类型,例如,a, *b = 'hello' 中的b 将被分配字符串'ello'。这可能看起来不错,但不可能对所有迭代都保持一致。

使加星标的目标成为一个元组而不是一个列表。这将与函数的*args 一致,但会使结果的进一步处理更加困难。

但是如你所见,这些功能目前还没有实现:

In [1]: a, *b, c = 'Hello!'
In [2]: print(a, b, c)
H ['e', 'l', 'l', 'o'] !

也许,可变列表更适合这种类型的解包。

【讨论】:

执行项目符号点 1 似乎很难。我的惊喜来自于我期望第 2 点成为惯例的快速,因为当我使用扩展参数时,我总是得到元组而不是其他类型的迭代。所以它烧到了我的皮层。

以上是关于为啥解包在 Python 中给出一个列表而不是一个元组?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Swift 2 偏爱强制解包而不是可选项?

为啥xml包在Python3中修改我的xml文件?

关于Python 解包,你需要知道的一切

为啥调用 python 列表的 [-1] 会给出这个输出? [复制]

你不了解的Python冷知识序列解包/列表前加星号*list

为啥这个 VBA 代码给出 -25 而不是 25?