初めに
リスト内表記、for及びwhileってどれが速いんじゃろ?と疑問を持ったので様々なコードを書いて計測してみた。
実行環境
python2.7
windows7
Intel Core i5 CPU 2.4GHz
メモリ 4.0 GB
測定対象
for 単独ループ(100万回)
for 2重ループ(1000回×1000回)
リスト内包表記(100万回)
リスト内包表記(1000回×1000回)
while 単独ループ(100万回)
while 2重ループ(1000回×1000回)
条件(詳しくは末尾のコード参照)
リストを作成する場合
+forの場合(range有り無し)
+ループ内にif文がある場合
何らかの合計値を算出する場合
+ループ内にif文がある場合
結果
単にリストを作るだけならリスト内包表記が最速だった。
if文が入ったりすると全体的にやや悪化し、forもリスト内包表記もあまり変わらなくなった。whileは2重ループで明らかに速度が落ちた。この理由はよくわからない。
合計値算出となると、リスト内包表記はforよりも遅くなった。これは100万個の和を取るsumに時間がかかっているということのように見える。
合計値算出+ifのところはリスト内包表記でもforでも変わらない結果となった。
結論
とりあえずリスト内包表記を書いておけば良いが、作成したリストを活かさない処理(単にsumを取るだけなど)だと、当該リストを他の関数(sum()等)で処理するためのコストが増大して遅くなる可能性がある。
whileは多重ループのifに注意すると良さそう。
実験コードたち
seq1 = range(10**6)
seq2 = range(10**3)
num1 = 10**6
num2 = 10**3
v = 10**10
def for1():
ls = []
for i in seq1:
ls.append(v)
#print len(ls)
def for2():
ls = []
for i in seq2:
for j in seq2:
ls.append(v)
#print len(ls)
def for_range1():
ls = []
for i in range(10**6):
ls.append(v)
#print len(ls)
def for_range2():
ls = []
for i in range(10**3):
for j in range(10**3):
ls.append(v)
#print len(ls)
def for_listnai1():
[v for i in seq1]
def for_listnai2():
[v for i in seq2 for j in seq2]
def for_listnai_range1():
[v for i in range(10**6)]
def for_listnai_range2():
[v for i in range(10**3) for j in range(10**3)]
def forsum1():
s = 0
for i in seq1:
s += v
def forsum2():
s = 0
for i in seq2:
for j in seq2:
s += v
def for_listnaisum1():
sum([v for i in seq1])
def for_listnaisum2():
sum([v for i in seq2 for j in seq2])
def while1():
i = 0
ls = []
while i < num1:
ls.append(v)
i+=1
def while2():
i = 0
ls = []
while i < num2:
j = 0
while j < num2:
ls.append(v)
j+=1
i+=1
def whilesum1():
i = 0
s = 0
while i < num1:
s += v
i+=1
def whilesum2():
i = 0
s = 0
while i < num2:
j = 0
while j < num2:
s += v
j+=1
i+=1
def forif1():
ls = []
for i in seq1:
if v % 2:
ls.append(v)
def forif2():
ls = []
for i in seq2:
for j in seq2:
if v % 2:
ls.append(v)
def forlistnaiif1():
[v for i in seq1 if v % 2]
def forlistnaiif2():
[v for i in seq2 for j in seq2 if v % 2]
def whileif1():
ls = []
i=0
while i <num1:
ls.append(v)
i+=1
def whileif2():
ls = []
i=0
while i <num2:
j=0
while j<num2 :
if v % 2:
ls.append(v)
j+=1
i+=1
def forifsum1():
s = 0
for i in seq1:
if v % 2:
s+=v
def forifsum2():
s = 0
for i in seq2:
for j in seq2:
if v % 2:
s+=v
def forlistnaiifsum1():
sum([v for i in seq1 if v % 2])
def forlistnaiifsum2():
sum([v for i in seq2 for j in seq2 if v % 2])
def whileifsum1():
s = 0
i=0
while i <num1:
s+=v
i+=1
def whileifsum2():
s=0
i=0
while i <num2:
j=0
while j<num2 :
if v % 2:
s+=v
j+=1
i+=1
時間測定コード
def exe(func,num=0):
import time
print "%s start:" % func
s = 0
for i in range(0,num):
start = time.time()
exec func
end = time.time()
s += end - start
print "%s finished: %d times." % (func,num)
print s
if __name__=='__main__':
exe("for1()",1)
exe("for2()",1)
exe("for_range1()",1)
exe("for_range2()",1)
exe("for_listnai1()",1)
exe("for_listnai2()",1)
exe("for_listnai_range1()",1)
exe("for_listnai_range2()",1)
exe("while1()",1)
exe("while2()",1)
exe("forsum1()",1)
exe("forsum2()",1)
exe("for_listnaisum1()",1)
exe("for_listnaisum2()",1)
exe("whilesum1()",1)
exe("whilesum2()",1)
exe("forif1()",1)
exe("forif2()",1)
exe("forlistnaiif1()",1)
exe("forlistnaiif2()",1)
exe("whileif1()",1)
exe("whileif2()",1)
exe("forifsum1()",1)
exe("forifsum2()",1)
exe("forlistnaiifsum1()",1)
exe("forlistnaiifsum2()",1)
exe("whileifsum1()",1)
exe("whileifsum2()",1)