Create List of Single Item Repeated n Times in Python
我知道单子上的理解可以做到这一点,但我想知道是否还有一个更短(更多的Python?)接近。
我想创建一系列长度不同的列表。每个列表将包含相同的元素e,重复n次(其中n=列表的长度)。如何创建列表,而不做
1 | [e for number in xrange(n)] |
对于每个列表?
你也可以写:
1 | [e] * n |
号
您应该注意,如果e是一个空列表,那么您会得到一个对同一个列表有n个引用的列表,而不是n个独立的空列表。
性能测试
乍一看,repeat似乎是创建具有n个相同元素的列表的最快方法:
1 2 3 4 | >>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000) 0.37095273281943264 >>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000) 0.5577236771712819 |
但是等等-这不是一个公平的测试…
1 2 | >>> itertools.repeat(0, 10) repeat(0, 10) # Not a list!!! |
。
函数
1 2 | >>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000) 1.7508119747063233 |
所以如果你想要一个列表,使用
1 2 | >>> [5] * 4 [5, 5, 5, 5] |
。
当要重复的项目是列表时要小心。不会克隆列表:所有元素都将引用同一列表!
1 2 3 4 5 6 7 | >>> x=[5] >>> y=[x] * 4 >>> y [[5], [5], [5], [5]] >>> y[0][0] = 6 >>> y [[6], [6], [6], [6]] |
。
Create List of Single Item Repeated n Times in Python
号不可变项
对于不可变项(如无、字符串、元组或冻结集),可以这样做:
1 | [e] * 4 |
。
请注意,这最好只用于列表中不可变的项(字符串、元组、冻结集),因为它们都指向内存中相同位置的相同项。当我必须用所有字符串的模式构建一个表时,我经常使用这个方法,这样就不必给出一对一的映射。
1 | schema = ['string'] * len(columns) |
可变项目
我已经使用Python很长一段时间了,我从来没有看到过一个用例,在这个用例中,我将使用一个可变的实例来完成上面的工作。相反,要得到一个可变的空列表、集合或dict,您应该这样做:
1 | list_of_lists = [[] for _ in columns] |
。
在这个上下文中,下划线只是一个一次性变量名。
如果你只有这个号码,那就是:
1 | list_of_lists = [[] for _ in range(4)] |
号
小心使用可变对象,当您更改其中一个对象时,它们都会更改,因为它们都是相同的对象:
1 2 | foo = [[]] *4 foo[0].append('x') |
号
foo现在返回:
1 | [['x'], ['x'], ['x'], ['x']] |
号
但对于不可变对象,您可以使其工作,因为您更改了引用,而不是对象:
1 2 3 4 5 6 7 8 9 | >>> 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([])] |
号
但同样,可变对象不适合这样做,因为就地操作更改了对象,而不是引用:
1 2 3 4 | 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的功能就是:
1 2 | import itertools it = itertools.repeat(e,n) |
当然,
正如其他人所指出的,对可变对象使用*运算符会重复引用,因此,如果更改一个对象,则会全部更改。如果您想创建可变对象的独立实例,xrange语法是实现这一点的最简单的方法。如果您被一个从未使用过的命名变量所困扰,您可以使用匿名下划线变量。
1 | [e for _ in xrange(n)] |
号
1 | [e] * n |
号
应该工作