2009-08-29 15 views
4

なぜ「列挙」は「xrange + lst [i]」よりも遅いのですか?なぜPythonの列挙は遅いのですか?

 

>>> from timeit import Timer 
>>> lst = [1,2,3,0,1,2]*1000 
>>> setup = 'from __main__ import lst' 
>>> s1 = """ 
for i in range(len(lst)): 
    elem = lst[i] 
""" 
>>> s2 = """ 
for i in xrange(len(lst)): 
    elem = lst[i] 
""" 
>>> s3 = """ 
for i, v in enumerate(lst): 
    elem = v 
""" 
>>> t1 = Timer(s1, setup); t2 = Timer(s2, setup); t3 = Timer(s3, setup) 
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000) 
(1.9263118636586494, 1.6119261665937992, 1.9606022553145719) 
>>> t1.timeit(3000), t2.timeit(3000), t3.timeit(3000) 
(1.93520258859715, 1.6145745478824836, 1.9529405971988041) 
 

EDIT:あなたはenumerate

for i in xrange(len(lst)): 
    elem = i, lst[i] 

答えて

14

あなたが適切に測定する場合は、差が(列挙この例ではxrangeより微視的に高速ですが、うまくノイズ内の)基本的にありませんわかります

$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i in xrange(len(lst)): elem=lst[i]' 
1000 loops, best of 3: 480 usec per loop 
$ python -mtimeit -s'lst=[1,2,3,0,1,2]*1000' 'for i, elem in enumerate(lst): pass' 
1000 loops, best of 3: 473 usec per loop 

(ところで、私はいつものtimeitを使用することをお勧めしますシェルのプロンプトは、コード内やインタプリタのプロンプトではなく、出力がきれいに整形され、使用可能で、時間の単位とすべての単位があるからです。

コードでは、列挙ケースで余分な割り当てがあります。つまり、forヘッダー句のリスト項目をvに割り当て、次にvelemに割り当てます。 xrangeの場合は、項目を一度だけelemに割り当てます。私の場合はもちろん、どちらの場合でも1回だけ割り当てます。とにかく何回も割り当てたいのですか?ループの本体にelemiを使って何をしているのかは、私が測定している2つの形式で同じことを行うことができます。列挙ケースには冗長性がありません。

5

より

for i, v in enumerate(lst): 
    elem = i, v 
遅く足かせている可能性があるため、なぜ は私が念頭に置いておきます。これを試してみてください:

>>> s3 = """ 
for i, elem in enumerate(lst): 
    pass 
""" 

更新アレックスは言及しなかったことをシェルプロンプトでtimeitを使用するための 2つの余分な理由:

(1)それがない「Nの最高の」あなたのために。
(2)意味のある結果を得るには何回反復する必要がありますか。

+2

Johnの答えが理にかなっている理由が明確でない場合は、enumerateによって生成された結果に、検索されたリスト要素が既に含まれています。 for-loopの変数でその名前を使用することで、それを明確にします。元のバージョンでは、検索を2回実行しました。 – SingleNegationElimination

+3

@TokenMacGuyと2つのコメントシッター: "すでに検索されたリスト要素が含まれています...あなたは2回の検索を実行しました":これは正しくありません。要素はリストから一度だけ抽出されます。 2つのバージョン間の違いは、「ルックアップ」を伴わないフォーム「x = y」の冗長な割り当てである。 –

関連する問題