[英]Best and/or fastest way to create lists in python
在 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 中創建和初始化列表的首選/最快方法是什么?
讓我們用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
>>>
*注意:在所有測試中,我都用xrange
替換了range
。 由於后者返回一個迭代器,它應該總是比前者快。
如果要查看列表長度為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()
要點在這里。
還有一種方法,雖然聽起來很奇怪,但在正確的姜黃中很方便。 如果您需要多次生成相同的列表(在我的情況下為roguelike 尋路和相關內容初始化矩陣),您可以將列表的副本存儲在元組中,然后在需要時將其轉換為列表。 它明顯比通過推導式生成列表快,並且與列表乘法不同,它適用於嵌套數據結構。
# 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()
瞧,在每次迭代中,您都會立即獲得相同列表的新副本!
我不知道為什么這么快,或者它是否可以在 CPython 3.4 之外的任何地方工作。
如果要創建一個遞增的列表,即每次加 1,請使用range
函數。 在range
中包含 start 參數並排除 end 參數,如下所示:
list(range(10,20))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
如果您想通過向前面的元素添加 2 來創建列表,請使用以下命令:
list(range(10,20,2))
[10, 12, 14, 16, 18]
這里的第三個參數是要采用的步長。 現在,您可以提供任何開始元素、結束元素和步長,並快速輕松地創建許多列表。
謝謝..!
快樂學習.. :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.