函数调用中的星号

135

我正在使用itertools.chain按照以下方式“展平”一个列表的列表:

uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))

这与说什么不同:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

9
请查看Python文档中的解包参数列表以获取更多信息。 - Kai
10
你还应该查看**运算符--它与*的作用相同,只不过是用于关键字参数。 - Sean Vieira
3个回答

205

*是"展开"操作符:它将类似列表的可迭代对象作为输入,并在函数调用中将其扩展为实际的位置参数。

因此,如果uniqueCrossTabs[[1, 2], [3, 4]],那么itertools.chain(*uniqueCrossTabs)itertools.chain([1, 2], [3, 4])相同。

这显然不同于只传递uniqueCrossTabs。在您的情况下,您有一个要展开的列表,而itertools.chain()的作用是返回一个迭代器,该迭代器在您传递给它的所有位置参数的连接上迭代,其中每个位置参数本身都是可迭代的。

换句话说,您想将uniqueCrossTabs中的每个列表作为参数传递给chain(),它将把它们链接在一起,但您没有将列表存储在单独的变量中,因此使用*运算符将列表的列表展开为几个列表参数。

chain.from_iterable()更适合此操作,因为它假定一开始只有一个可迭代的可迭代对象。然后,您的代码就变得非常简单:

uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

就像 JavaScript 中的 _Spread 运算符(...)一样工作!我明白了。 - Константин Ван

83

它将序列拆分为函数调用的单独参数。

>>> def foo(a, b=None, c=None):
...   print a, b, c
... 
>>> foo([1, 2, 3])
[1, 2, 3] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
...   print a
... 
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

32

只是解释这个概念或使用它的另一种方式。

import random

def arbitrary():
    return [x for x in range(1, random.randint(3,10))]

a, b, *rest = arbitrary()

# a = 1
# b = 2
# rest = [3,4,5]

2
这个答案并不特别适用于问题,但是星号的一个重要应用是函数定义中的def func(a, b, *args):。在同样的思路下,另一个重要的应用是在函数定义中:def func(a, b, *args):。更多信息请参见此答案 - ASL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接