多余的位置参数,解包参数列表或元组,以及扩展的可迭代解包

时间:2010-07-08 01:33:24

标签: python list tuples

这个问题会很长,所以我先发制人道歉。

在Python中,我们可以在以下三种情况下使用*:

我。在定义一个我们想要使用任意数量的参数调用的函数时,例如in this example

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

在这种情况下,多余的位置参数被收集到元组中。

II。相反的情况是,参数已经在列表元组中,我们希望将它们解压缩为函数调用需要单独的位置参数,例如in this example

>>> range(3, 6)             # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # call with arguments unpacked from a list
[3, 4, 5]

III。从Python 3开始,*也用于扩展 list 元组解包的上下文中,例如{{3对于元组:

>>> a, *b, c = range(5)
>>> b
[1, 2, 3]

或列表:

>>> [a, *b, c] = range(5)
>>> b
[1, 2, 3]

在这两种情况下,解包的所有未分配给任何强制性表达式的项目都将分配给列表

所以这就是问题:如果,额外的args被收集到元组中,而在 III 的情况下,额外的项目被分配到列表。这有什么不一样?我能找到的唯一解释是在PEP 3132中说:

  
    

讨论的可能变化是:

         

[...]

         

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

  

然而,从教学角度来看,缺乏一致性是有问题的,特别是考虑到如果你想处理结果,你总是可以说列表(b)(假设上面例子中的b是一个元组)。我错过了什么吗?

2 个答案:

答案 0 :(得分:8)

你错过了一个。

IV。此外,在Python 3中,参数列表中的裸*标记位置参数的结束,允许keyword-only arguments

def foo(a, b, *, key = None):
    pass

这可以称为foo(1, 2, key = 3),但不能称为foo(1, 2, 3)

答案 1 :(得分:7)

  

在Python中我们可以使用*   以下三种情况:

您的意思是前缀 *,当然 - 中缀 *用于乘法。

  

但是,从教学方面来说   透视这种缺乏一致性   是有问题的,特别是考虑到这一点   如果你想处理结果,   你总是可以说清单(b)(假设   上面例子中的b是一个元组)。   我错过了什么吗?

我会说设计问题(旧的和很长的牙齿!)是因为当你接收到任意参数时,你将它们作为一个元组,当一个列表在许多人中更有用没有真正缺点的情况(在函数调用开销 - 序列解包的上下文中,制作列表而不是元组可能需要的额外处理和内存的微小量可忽略不计,为此问题;制作列表以及元组所需的额外处理和内存实际上更令人讨厌。)

你可以用元组而不是列表来做很少的事情 - 基本上,只是对它进行哈希处理(用作设置项或字典键) - 而列表提供了更多的额外功能,而不是只是为了改变它而 ...... countindex等方法也很有用。