在Python中创build重复n次单项的列表
我知道一个列表理解会做到这一点,但我想知道是否有更短(更Pythonic?)的方法。
我想创build一系列不同长度的列表。 每个列表将包含相同的元素e,重复n次(其中n =列表的长度)。 如何创build列表,而不做
[e for number in xrange(n)]
为每个列表?
你也可以写:
[e] * n
你应该注意,如果e是例如一个空列表,你会得到一个列表,其中n个引用同一个列表,而不是n个独立的空列表。
性能testing
乍一看,重复是用n个相同元素创build列表的最快方式:
>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000) 0.37095273281943264 >>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000) 0.5577236771712819
但是等等 – 这不是一个公平的testing…
>>> itertools.repeat(0, 10) repeat(0, 10) # Not a list!!!
函数itertools.repeat
实际上并不创build列表,它只是创build一个对象,可以用来创build一个列表,如果你愿意! 让我们再试一次,但转换成一个列表:
>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000) 1.7508119747063233
所以如果你想要一个列表,使用[e] * n
。 如果你想要生成元素,请使用repeat
。
>>> [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]]
在Python中创build重复n次单项的列表
不变的物品
对于不可变的项目,如无,string,元组或frozensets,你可以这样做:
[e] * 4
请注意,这最好只用于列表中不可变的项目(string,元组,frozensets),因为它们都指向内存中同一位置的相同项目。 当我必须用一个所有string的模式构build一个表格时,我经常使用它,所以我不必一一给出一个映射。
schema = ['string'] * len(columns)
可变的项目
我已经使用Python很长一段时间了,我从来没有见过一个用例,我会做一个可变的实例上述。 相反,要得到一个可变的空列表,设置或字典,你应该这样做:
list_of_lists = [[] for _ in columns]
在这种情况下,下划线只是一个一次性的variables名称。
如果你只有号码,那将是:
list_of_lists = [[] for _ in range(4)]
_
并不是特别的,但是如果你不打算使用variables并使用其他名字,你的编码环境风格检查器可能会抱怨。
使用具有可变项目的不可变方法的注意事项:
要小心这个可变对象 ,当你改变它们之一时,它们都会改变,因为它们都是同一个对象:
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'])]
Itertools只是为了这个function:
import itertools it = itertools.repeat(e,n)
当然itertools
给你一个迭代器而不是一个列表。 [e] * n
给你一个列表,但是,根据你将要用这些序列做什么, itertools
变种可以更有效率。
正如其他人指出的那样,使用*运算符作为可变对象会复制引用,所以如果更改引用,则可以将其全部更改。 如果你想创build一个可变对象的独立实例,那么你的xrange语法就是最好的Pythonic方法。 如果您有一个永远不会使用的命名variables,您可以使用匿名下划线variables。
[e for _ in xrange(n)]
[e] * n
应该工作