2016-05-11 4 views
-1

次の2つのスニペットのパフォーマンスが同じであるかどうかはわかりません。一時変数付きのPythonパフォーマンス

CODE1:

for fid1 in FId1: 
    if fid1 in [i['FId'] for i in entity['F']]: 
     res.append([intId1,fid1,entity['Id'],intId2]) 

CODE2:

temp = [i['FId'] for i in entity['F']] 
tempid = entity['Id'] 
for fid1 in FId1: 
     if fid1 in temp: 
      res.append([intId1,fid1,tempid,intId2]) 

基本的には、ループの中で私は、エンティティを変更しないでください。

私はCode1では、最適化がなければ、すべてのループでそのリストを生成すると思います。それは読みやすくなりますが、それは遅くなるでしょうか?

したがって、私は一時的にリストを生成するようにtempを格納しようとします。

パフォーマンスはこのタスクにとって非常に重要です。

+2

まだプロファイルしましたか? –

+0

また、 'temp'を' set'にしたいでしょう( 'i ['FId']'がハッシュ可能であると仮定します)。 – chepner

答えて

3

はい、正確には、最初のコードはすべての反復に対して一時リストを生成します。これはCPython(ネイティブPythonインタプリタ)に当てはまります。技術的には、コード2で使用した最適化はprecomputationと呼ばれています。

しかし、PyPyのようなオプティマイザを使用すると、リストが変更されないというこのインスタンスを検出して定数として保存する可能性があるため、PyPyと異なる可能性があります。

2

パフォーマンスが重要な場合は、測定してください。

パフォーマンスを測定しない場合、達成しているパフォーマンスはわかりません。さらに重要なことに、将来の変更によってパフォーマンスが改善されるか悪化するかはわかりません。

2

ループ外のリストを作成するだけでなく、それをset(または定数であればfrozenset)に変更すると、O(1)メンバーシップテスト時間が発生します。

>>> timeit.timeit('123456 in s', setup='s = frozenset(xrange(1000000))', number=1000) 
7.14463625257622e-05 
>>> timeit.timeit('123456 in l', setup='l = list(xrange(1000000))', number=1000) 
2.899147340951913 
関連する問題