创建重复N次的单个项目的列表


522

我想创建一系列长度不一的列表。每个列表将包含相同的元素e,重复n次数(其中n=列表的长度)。

如何创建列表,而不[e for number in xrange(n)]对每个列表使用列表理解?

Answers:


777

您还可以编写:

[e] * n

您应该注意,例如,如果e是一个空列表,您将得到一个具有n个指向同一列表的引用的列表,而不是n个独立的空列表。

性能测试

乍看之下,似乎是重复是创建一个具有n个相同的元素列表的最快方法:

>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819

但是等等-这不是一个公平的测试...

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!

该函数itertools.repeat实际上并没有创建列表,它只是创建一个对象,您可以根据需要使用该对象来创建列表!让我们再试一次,但转换为列表:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233

因此,如果您想要列表,请使用[e] * n。如果要延迟生成元素,请使用repeat


23
创建具有相同元素的列表的性能极不可能成为python程序性能的关键组成部分。
亚瑟

11
如上所述,如果e为空列表,[[]] * n可能会产生意外结果。要创建唯一的空子列表,请使用以下理解:[[] for i in range(0,n)]
Josiah Yoder

149
>>> [5] * 4
[5, 5, 5, 5]

当重复的项目是列表时,请当心。该列表将不会被克隆:所有元素都将引用同一列表!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]

80

在Python中创建重复n次的单项列表

不变物品

对于不可变的项目,例如“无”,布尔值,整数,浮点数,字符串,元组或Frozensets,可以这样进行:

[e] * 4

请注意,这最好仅与列表中的不可变项(字符串,元组,frozensets)一起使用,因为它们都指向内存中同一位置的同一项。当我必须构建一个包含所有字符串的架构的表时,我会经常使用它,这样就不必提供高度冗余的一对一映射。

schema = ['string'] * len(columns)

可变项

我已经使用Python很长时间了,而且从未见过用可变实例执行上述操作的用例。相反,要获取可变的空列表,集合或字典,您应该执行以下操作:

list_of_lists = [[] for _ in columns]

在这种情况下,下划线只是一个简单的变量名。

如果只有号码,那将是:

list_of_lists = [[] for _ in range(4)]

_不是真的很特别,但你的编码环境风格检查可能会抱怨,如果你不打算使用的变量和使用的其他任何名称。


对可变项使用不可变方法的注意事项:

当心使用可变对象,当您更改其中一个对象时,它们都会更改,因为它们都是同一对象:

foo = [[]] * 4
foo[0].append('x')

foo现在返回:

[['x'], ['x'], ['x'], ['x']]

但是对于不可变的对象,您可以使其起作用,因为您可以更改引用,而不是对象:

>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]

>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]

但同样,可变对象对此没有好处,因为就地操作会更改对象,而不是引用:

l = [set()] * 4
>>> l[0] |= set('abc')    
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]

26

Itertools具有此功能:

import itertools
it = itertools.repeat(e,n)

当然可以itertools为您提供迭代器,而不是列表。[e] * n为您提供了一个列表,但是根据您对这些序列的处理方式,itertools变体可能会更加有效。


12

正如其他人指出的那样,对可变对象使用*运算符会重复引用,因此,如果更改一个,则会全部更改。如果要创建可变对象的独立实例,则xrange语法是执行此操作的最Python方式。如果您有一个从未使用过的命名变量而感到困扰,则可以使用匿名下划线变量。

[e for _ in xrange(n)]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.