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

chi*_*der 460 python list-comprehension multiplication replicate

我知道列表理解会做到这一点,但我想知道是否有更短(和更多Pythonic?)的方法.

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

__PRE__

对于每个清单?

Mar*_*ers 696

你也可以写:

[e] * n
Run Code Online (Sandbox Code Playgroud)

您应该注意,如果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
Run Code Online (Sandbox Code Playgroud)

但等等 - 这不是一个公平的考验......

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!
Run Code Online (Sandbox Code Playgroud)

该函数itertools.repeat实际上并不创建列表,它只是创建一个可用于创建列表的对象,如果您愿意!让我们再试一次,但转换成一个列表:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233
Run Code Online (Sandbox Code Playgroud)

因此,如果您想要一个列表,请使用[e] * n.如果你想懒洋洋地生成元素,请使用repeat.

  • 创建具有相同元素的列表的性能极不可能是python程序性能的关键组成部分. (20认同)
  • 如上所述,如果e是空列表`[[]]*n`会产生意外结果.要创建[唯一的空子列表](/sf/answers/554730151/),请使用for-comprehension:`[[] for i in range(0,n)]` (8认同)

gae*_*fan 130

>>> [5] * 4
[5, 5, 5, 5]
Run Code Online (Sandbox Code Playgroud)

当重复的项目是列表时要小心.该列表不会被克隆:所有元素都将引用相同的列表!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
Run Code Online (Sandbox Code Playgroud)

  • @蒂莫。是的。外部列表存储对同一内部列表的四个引用。 (3认同)
  • 是否有意义?创建一个列表,然后更改一个元素,然后整个列表都会更改? (2认同)

Aar*_*all 65

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

不可变的物品

对于不可变项,如None,字符串,元组或frozensets,您可以这样做:

[e] * 4
Run Code Online (Sandbox Code Playgroud)

请注意,这最好只用于列表中的不可变项(字符串,元组,frozensets),因为它们都指向内存中相同位置的相同项.当我必须使用所有字符串的模式构建一个表时,我经常使用它,这样我就不必给出一对一的映射.

schema = ['string'] * len(columns)
Run Code Online (Sandbox Code Playgroud)

可变物品

我已经使用了Python很长一段时间了,我从来没有见过一个用例,我会用一个可变实例来做上面的事情.相反,要获得一个可变的空列表,设置或字典,你应该做这样的事情:

list_of_lists = [[] for _ in columns]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,下划线只是一个一次性的变量名.

如果您只有这个号码,那就是:

list_of_lists = [[] for _ in range(4)]
Run Code Online (Sandbox Code Playgroud)

_不是特别的,但如果您不打算使用该变量并使用任何其他名称,您的编码环境样式检查器可能会抱怨.


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

注意使用可变对象执行此操作,当您更改其中一个时,它们都会更改,因为它们都是相同的对象:

foo = [[]] * 4
foo[0].append('x')
Run Code Online (Sandbox Code Playgroud)

foo现在返回:

[['x'], ['x'], ['x'], ['x']]
Run Code Online (Sandbox Code Playgroud)

但是对于不可变对象,您可以使它工作,因为您更改了引用,而不是对象:

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

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

l = [set()] * 4
>>> l[0] |= set('abc')    
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Run Code Online (Sandbox Code Playgroud)


Joc*_*zel 25

Itertools有一个功能:

import itertools
it = itertools.repeat(e,n)
Run Code Online (Sandbox Code Playgroud)

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


W.P*_*ill 11

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

[e for _ in xrange(n)]
Run Code Online (Sandbox Code Playgroud)


小智 9

如果您正在寻找简单的重复,例如:

[1, 2, 3, 1, 2, 3, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

只需使用:

[1, 2, 3] * 3
Run Code Online (Sandbox Code Playgroud)

但如果您正在寻找:

[1, 1, 1, 2, 2, 2, 3, 3, 3]
Run Code Online (Sandbox Code Playgroud)

这个更好,但需要更多时间:

numpy.concatenate([([i]*3) for i in [1,2,3]], axis=0)
Run Code Online (Sandbox Code Playgroud)