7

考虑一个定义为的函数:

def fun(a, *args):
    print(type(args), args)

调用时,它将额外的位置参数打包为tuple

>>> fun(2, 3, 4)
<class 'tuple'> (3, 4)

我想在函数参数之外实现类似的事情。所以,我想我可以通过扩展的可迭代解包来实现同样的事情,但它总是将东西打包为一个列表,而不是一个元组

# RHS is a tuple
>>> (a, *args) = (2, 3, 4)
>>> type(args)
<class 'list'>
>>> args
[3, 4]  #but args is not a tuple!

使其与以下内容没有什么不同:

# RHS is a list
>>> (a, *args) = [2, 3, 4]
>>> type(args)
<class 'list'>
>>> args
[3, 4]

我可以理解,这也是PEP中提出的方式。

我在问是否有另一种方法来实现我想要的。

当然,我可以args稍后通过以下操作转换为元组:

>>> args = tuple(args)
>>> args
(3, 4)

如果这不能在分配期间直接实现。

4

2 回答 2

3

我知道的最接近的方法(我承认,并没有直接回答你的问题)只是对元组进行切片:

t = (2,3,4)
a, args = t[0], t[1:]

>>> type(args)
<class 'tuple'>

是的,它很冗长,但至少它避免了中间列表。

于 2019-12-16T16:01:00.573 回答
1

这里还有一些额外的注意事项需要牢记。RHS 的类型不限于列表或元组。您可以解压缩任意迭代:

a, *args = itertools.repeat('hi', 3)

没有充分的理由args特别应该是任何一种类型。结果是一个列表是有道理的,因为它应该能够累积任意数量的元素,但是在 C 代码中没有重大的相关差异,至少在 CPython 中是这样。

函数参数几乎必须是元组,因为函数可以返回打包对象和闭包。args在这种情况下,您不希望能够修改:

def func(arg, *args):
    assert args
    def blah():
        return args[0]
    return args, blah

这有点做作,但说明了为什么args可以被认为是公共的并且在函数中不应该是可变的。

话虽如此,这是一种通用方法,用于获取所需的解包,无论 RHS 类型如何:

t = (2, 3, 4)
it = iter(t)
a, args = next(it), tuple(it)
于 2019-12-16T19:41:30.913 回答