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

Ale*_*lis 5 python tuples list

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

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

I.在定义一个我们想要用任意数量的参数调用的函数时,例如在这个例子中:

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))
Run Code Online (Sandbox Code Playgroud)

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

II.相反的情况是,当参数已经在列表元组中时,我们希望为需要单独位置参数的函数调用解包它们,例如在本例中:

>>> 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]
Run Code Online (Sandbox Code Playgroud)

III.从Python 3开始,*也用于扩展列表元组解包的上下文中,例如在这个示例中用于元组:

>>> a, *b, c = range(5)
>>> b
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

或列表:

>>> [a, *b, c] = range(5)
>>> b
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

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

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

讨论的可能变化是:

[...]

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

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

Chr*_* B. 8

你错过了一个.

IV.此外,在Python 3中,*参数列表中的裸标记位置参数的结束,允许仅关键字参数.

def foo(a, b, *, key = None):
    pass
Run Code Online (Sandbox Code Playgroud)

这可以被召唤foo(1, 2, key = 3)但不是foo(1, 2, 3).


Ale*_*lli 7

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

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

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

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

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