for i in range(10): value = a[i]これだと、インデックスiが有効かどうかわからないのでどうにかしたい。
(例1)
とりあえず長さをチェックして参照する。
for i in range(10): if i < len(a): value = a[i]これはループで毎回len(a)するのでいかにも遅そう。
(例2)
シーケンスの長さが変わらないのであればループの前にあらかじめ長さをとっておこう。
alen = len(a) for i in range(10): if i < alen: value = a[i]
(例3)
とりあえず参照して例外を拾おう。
for i in range(10): try: value = a[i] except IndexError: pass
どれを使うのがよさげなのか計ってみよう。
テスト用スクリプト
#!/usr/bin/env python import timeit # インデックスiが範囲内の場合のセットアップ setup1 = """ a = [ 1, 2, 3 ] alen = len(a) i = 1 """ # インデックスiが範囲外の場合のセットアップ setup2 = """ a = [ 1, 2, 3 ] alen = len(a) i = 5 """ # 例1用ステートメント stmt1 = """ if i < len(a): a[i] else: pass """ # 例2用ステートメント stmt2 = """ if i < alen: a[i] else: pass """ # 例3用ステートメント stmt3 = """ try: a[i] except IndexError: pass """ print timeit.Timer(setup = setup1, stmt = stmt1).timeit() print timeit.Timer(setup = setup1, stmt = stmt2).timeit() print timeit.Timer(setup = setup1, stmt = stmt3).timeit() print timeit.Timer(setup = setup2, stmt = stmt1).timeit() print timeit.Timer(setup = setup2, stmt = stmt2).timeit() print timeit.Timer(setup = setup2, stmt = stmt3).timeit()実行結果
# インデックスが範囲内 0.361014127731 # 例1 0.125293016434 # 例2 0.128052949905 # 例3 # インデックスが範囲外 0.284233808517 # 例1 0.101886034012 # 例2 1.82788801193 # 例3
例外処理で実装した場合(例3)のインデックスが範囲外になる時が飛びぬけて遅い。
つまり、例外発生のコストは結構大きい。
例外発生が頻繁に発生することが予測される場合、if...elseで簡単に
代替できるのであればif...elseを使ったほうが高速。
0 件のコメント:
コメントを投稿