在python中,据我所知,至少有3到4种方法可以创建和初始化给定大小的列表:
使用append
进行简单循环:
my_list = []
for i in range(50):
my_list.append(0)
使用+=
进行简单循环:
my_list = []
for i in range(50):
my_list += [0]
列表理解:
my_list = [0 for i in range(50)]
列表和整数乘法:
my_list = [0] * 50
在这些例子中,我不认为会有任何性能差异,因为这些列表只有50个元素,但如果我需要一个包含一百万个元素的列表呢?使用xrange
会有什么改进吗?哪个是在python中创建和初始化列表的首选/最快方法?
答案 0 :(得分:38)
让我们用timeit.timeit
运行一些时间测试*:
>>> from timeit import timeit
>>>
>>> # Test 1
>>> test = """
... my_list = []
... for i in xrange(50):
... my_list.append(0)
... """
>>> timeit(test)
22.384258893239178
>>>
>>> # Test 2
>>> test = """
... my_list = []
... for i in xrange(50):
... my_list += [0]
... """
>>> timeit(test)
34.494779364416445
>>>
>>> # Test 3
>>> test = "my_list = [0 for i in xrange(50)]"
>>> timeit(test)
9.490926919482774
>>>
>>> # Test 4
>>> test = "my_list = [0] * 50"
>>> timeit(test)
1.5340533503559755
>>>
如上所示,到目前为止,最后一种方法是最快的。
但是,它应仅与不可变项(如整数)一起使用。这是因为它将创建一个列表,其中包含对同一项的引用。
以下是演示:
>>> lst = [[]] * 3
>>> lst
[[], [], []]
>>> # The ids of the items in `lst` are the same
>>> id(lst[0])
28734408
>>> id(lst[1])
28734408
>>> id(lst[2])
28734408
>>>
这种行为通常是不受欢迎的,可能会导致代码中的错误。
如果您有可变项(例如列表),那么您应该使用仍然非常快速的列表理解:
>>> lst = [[] for _ in xrange(3)]
>>> lst
[[], [], []]
>>> # The ids of the items in `lst` are different
>>> id(lst[0])
28796688
>>> id(lst[1])
28796648
>>> id(lst[2])
28736168
>>>
*注意:在所有测试中,我将range
替换为xrange
。由于后者返回迭代器,因此它应该总是比前者快。
答案 1 :(得分:17)
如果要查看列表n
的长度的依赖关系:
我测试了列表长度,最多n = 10000,行为保持不变。因此整数乘法方法是最快的差异。
对于超过约300个元素的列表,您应该考虑numpy。
基准代码:
import time
def timeit(f):
def timed(*args, **kwargs):
start = time.clock()
for _ in range(100):
f(*args, **kwargs)
end = time.clock()
return end - start
return timed
@timeit
def append_loop(n):
"""Simple loop with append"""
my_list = []
for i in xrange(n):
my_list.append(0)
@timeit
def add_loop(n):
"""Simple loop with +="""
my_list = []
for i in xrange(n):
my_list += [0]
@timeit
def list_comprehension(n):
"""List comprehension"""
my_list = [0 for i in xrange(n)]
@timeit
def integer_multiplication(n):
"""List and integer multiplication"""
my_list = [0] * n
import numpy as np
@timeit
def numpy_array(n):
my_list = np.zeros(n)
import pandas as pd
df = pd.DataFrame([(integer_multiplication(n), numpy_array(n)) for n in range(1000)],
columns=['Integer multiplication', 'Numpy array'])
df.plot()
要点here。
答案 2 :(得分:1)
还有一种方法虽然听起来很奇怪,但在正确的情况下却很方便。如果你需要多次生成相同的列表(在我的情况下初始化roguelike pathfinding and related stuff的矩阵),你可以在列表中存储列表的副本,然后在需要时将其转换为列表。它比通过理解生成列表明显更快,并且与列表乘法不同,它适用于嵌套数据结构。
# In class definition
def __init__(self):
self.l = [[1000 for x in range(1000)] for y in range(1000)]
self.t = tuple(self.l)
def some_method(self):
self.l = list(self.t)
self._do_fancy_computation()
# self.l is changed by this method
# Later in code:
for a in range(10):
obj.some_method()
Voila,在每次迭代中,您都可以立即获得相同列表的全新副本!
我没有任何想法为什么这么快,或者它是否适用于CPython 3.4以外的任何地方。
答案 3 :(得分:0)
如果要创建列表增量,即每次在范围参数中的列表参数中使用范围函数时加1,则如下所示,将终止值排除在外
list(range(10,20))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
如果您希望每次在previuos元素上添加2时创建列表,请使用此功能,这是范围函数中的第三个值
list(range(10,20,2))
[10, 12, 14, 16, 18]
现在,您可以提供任何开始元素,结束元素和步骤,并更快,更轻松地创建许多列表。
谢谢..
学习愉快...:)