函数调用中的星号

我以这种方式使用 itertools.chain“扁平化”一个列表列表:

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

这和说:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))
54181 次浏览

*是“ splat”操作符: 它接受一个类似 list 的迭代器作为输入,并将其展开为函数调用中的实际位置参数。

所以如果 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))

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

>>> 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)

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

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]