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

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

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

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

I want to create a series of lists, all of varying lengths. Each list will contain the same element e, repeated n times (where n = length of the list).

How do I create the lists, without using a list comprehension [e for number in xrange(n)] for each list?


回答 0

您还可以编写:

[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

You can also write:

[e] * n

You should note that if e is for example an empty list you get a list with n references to the same list, not n independent empty lists.

Performance testing

At first glance it seems that repeat is the fastest way to create a list with n identical elements:

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

But wait – it’s not a fair test…

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

The function itertools.repeat doesn’t actually create the list, it just creates an object that can be used to create a list if you wish! Let’s try that again, but converting to a list:

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

So if you want a list, use [e] * n. If you want to generate the elements lazily, use repeat.


回答 1

>>> [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]]
>>> [5] * 4
[5, 5, 5, 5]

Be careful when the item being repeated is a list. The list will not be cloned: all the elements will refer to the same list!

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

回答 2

在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'])]

Create List of Single Item Repeated n Times in Python

Immutable items

For immutable items, like None, bools, ints, floats, strings, tuples, or frozensets, you can do it like this:

[e] * 4

Note that this is best only used with immutable items (strings, tuples, frozensets, ) in the list, because they all point to the same item in the same place in memory. I use this frequently when I have to build a table with a schema of all strings, so that I don’t have to give a highly redundant one to one mapping.

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

Mutable items

I’ve used Python for a long time now, and I have never seen a use-case where I would do the above with a mutable instance. Instead, to get, say, a mutable empty list, set, or dict, you should do something like this:

list_of_lists = [[] for _ in columns]

The underscore is simply a throwaway variable name in this context.

If you only have the number, that would be:

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

The _ is not really special, but your coding environment style checker will probably complain if you don’t intend to use the variable and use any other name.


Caveats for using the immutable method with mutable items:

Beware doing this with mutable objects, when you change one of them, they all change because they’re all the same object:

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

foo now returns:

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

But with immutable objects, you can make it work because you change the reference, not the object:

>>> 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([])]

But again, mutable objects are no good for this, because in-place operations change the object, not the reference:

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

回答 3

Itertools具有此功能:

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

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

Itertools has a function just for that:

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

Of course itertools gives you a iterator instead of a list. [e] * n gives you a list, but, depending on what you will do with those sequences, the itertools variant can be much more efficient.


回答 4

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

[e for _ in xrange(n)]

As others have pointed out, using the * operator for a mutable object duplicates references, so if you change one you change them all. If you want to create independent instances of a mutable object, your xrange syntax is the most Pythonic way to do this. If you are bothered by having a named variable that is never used, you can use the anonymous underscore variable.

[e for _ in xrange(n)]

回答 5

[e] * n

应该管用

[e] * n

should work