python - 有没有办法在解包时将 splat-assign 分配为元组而不是列表?
问题描述
我最近惊讶地发现“splat”(一元 *)运算符总是list
在项目解包期间将切片捕获为 a,即使被解包的序列具有另一种类型:
>>> x, *y, z = tuple(range(5))
>>> y
[1, 2, 3] # list, was expecting tuple
比较如何在不拆包的情况下编写此作业:
>>> my_tuple = tuple(range(5))
>>> x = my_tuple[0]
>>> y = my_tuple[1:-1]
>>> z = my_tuple[-1]
>>> y
(1, 2, 3)
它也与 splat 运算符在函数参数中的行为不一致:
>>> def f(*args):
... return args, type(args)
...
>>> f()
((), <class 'tuple'>)
为了y
在解包后恢复为元组,我现在必须写:
>>> x, *y, z = tuple(range(5))
>>> y = tuple(y)
这仍然比基于切片的语法好得多,但仍然遭受我认为非常不必要和意外的优雅损失。有没有办法在y
没有分配后处理的情况下恢复为元组而不是列表?
我试图y
通过编写来强制 python 解释为一个元组x, *(*y,), z = ...
,但它仍然以列表的形式结束。当然还有一些愚蠢的事情,比如x, *tuple(y), z
在 python 中不起作用。
我目前使用的是 Python 3.8.3,但也欢迎涉及更高版本的解决方案/建议/解释(当它们可用时)。
解决方案
这是设计使然。引用有关分配的官方文档:
...可迭代的第一项从左到右分配给加星标目标之前的目标。可迭代的最终项目分配给加星标的目标之后的目标。然后将迭代中剩余项目的列表分配给加星标的目标(列表可以为空)。
Python 用户很可能y
之后想要改变你的,所以list
选择了类型而不是tuple
.
引用我通过此相关问题中的链接找到的PEP 3132的接受部分:
在对 python-3000 列表 [1] 进行简短讨论后,Guido 以当前形式接受了 PEP。讨论的可能变化是:
只允许星号表达式作为 exprlist 中的最后一项。这将稍微简化解包代码,并允许为带星号的表达式分配一个迭代器。这种行为被拒绝了,因为它太令人惊讶了。
尝试为加星标的目标赋予与源可迭代相同的类型,例如,b in
a, *b = "hello"
将被分配字符串"ello"
。这可能看起来不错,但不可能与所有可迭代对象保持一致。使加星标的目标成为元组而不是列表。这将与函数的 一致
*args
,但会使结果的进一步处理更加困难。
因此,y = tuple(y)
之后转换是您唯一的选择。
推荐阅读
- c# - Serilog - ForContext 将字典值视为复杂对象
- c++ - 自定义 C++ 快速排序问题
- git - 将本地提交的更改推送到新分支
- reactjs - 即使变量相同,react useState 也会进入无限循环
- mongodb - 带有子查询的 MongoDB $in
- git - 如何将 git 存储库目录转换为包含子模块的存储库?
- aem - 将特定路径的搜索结果显示在顶部而不是其他路径
- wpf - 错误 XLS0502 'WindowsFormsHost' 类型不支持直接内容
- symfony - 我无法从 JWT 获取用户
- python - 我如何在 python 中使用 asyncio 接收请求的大小