私の質問への答えとして、2つのリストが同じである1ベースの位置を見つけて、Cライブラリitertoolsを使用して処理を高速化するためのヒントを得ました。
確認するために、cProfileを使用して次のテストをコーディングしました。
from itertools import takewhile, izip
def match_iter(self, other):
return sum(1 for x in takewhile(lambda x: x[0] == x[1],
izip(self, other)))
def match_loop(self, other):
element = -1
for element in range(min(len(self), len(other))):
if self[element] != other[element]:
element -= 1
break
return element +1
def test():
a = [0, 1, 2, 3, 4]
b = [0, 1, 2, 3, 4, 0]
print("match_loop a=%s, b=%s, result=%s" % (a, b, match_loop(a, b)))
print("match_iter a=%s, b=%s, result=%s" % (a, b, match_iter(a, b)))
i = 10000
while i > 0:
i -= 1
match_loop(a, b)
match_iter(a, b)
def profile_test():
import cProfile
cProfile.run('test()')
if __name__ == '__main__':
profile_test()
関数match_iter()はitertoolsを使用しており、関数match_loop()はプレーンPythonを使用する前に実装したものです。
関数test()は、2つのリストを定義し、2つの関数の結果をリストに出力して、機能していることを確認します。両方の結果の期待値は5で、これはリストが等しい場合の長さです。次に、両方の関数で10,000回ループします。
最後に、profile_test()を使用して全体のプロファイルを作成します。
私が学んだことは、izipはpython3のitertoolsに実装されておらず、少なくとも私が使用しているdebianwheezywhitでは実装されていないということでした。だから私はpython2.7でテストを実行しました
結果は次のとおりです。
python2.7 match_test.py
match_loop a=[0, 1, 2, 3, 4], b=[0, 1, 2, 3, 4, 0], result=5
match_iter a=[0, 1, 2, 3, 4], b=[0, 1, 2, 3, 4, 0], result=5
180021 function calls in 0.636 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.636 0.636 <string>:1(<module>)
1 0.039 0.039 0.636 0.636 match_test.py:15(test)
10001 0.048 0.000 0.434 0.000 match_test.py:3(match_iter)
60006 0.188 0.000 0.275 0.000 match_test.py:4(<genexpr>)
50005 0.087 0.000 0.087 0.000 match_test.py:4(<lambda>)
10001 0.099 0.000 0.162 0.000 match_test.py:7(match_loop)
20002 0.028 0.000 0.028 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
10001 0.018 0.000 0.018 0.000 {min}
10001 0.018 0.000 0.018 0.000 {range}
10001 0.111 0.000 0.387 0.000 {sum}
不思議に思うのは、cumtimeの値を見ると、私のプレーンなpythonバージョンの値は10,000ループで0.162秒で、match_iterバージョンの値は0.434秒です。
一つには、Pythonは非常に高速で素晴らしいので、心配する必要はありません。しかし、これは正しいでしょうか?Cライブラリがジョブを完了するのに単純なPythonコードの2倍以上の時間がかかるということですか?それとも私は致命的な間違いをしていますか?
確認するために、python2.6でもテストを実行しました。これはさらに高速のようですが、ループとitertoolsの違いは同じです。
誰が経験豊富で喜んで手伝ってくれますか?