python2.7でリスト内包表記、for及びwhileの速度を計測してみた。

初めに
---
リスト内表記、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は２重ループで明らかに速度が落ちた。この理由はよくわからない。
合計値算出となると、リスト内包表記はforよりも遅くなった。これは100万個の和を取るsumに時間がかかっているということのように見える。
合計値算出+ifのところはリスト内包表記でもforでも変わらない結果となった。
![determine.png](https://qiita-image-store.s3.amazonaws.com/0/70480/1bdcbe20-d37d-b899-6d46-b2087d6acc4d.png)

結論
---
とりあえずリスト内包表記を書いておけば良いが、作成したリストを活かさない処理（単にsumを取るだけなど）だと、当該リストを他の関数(sum()等)で処理するためのコストが増大して遅くなる可能性がある。
whileは多重ループのifに注意すると良さそう。

実験コードたち
---
```py
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
```

時間測定コード
---
```py

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)
```