Pythonでのさまざまな同等の形式を比較しfilter(xs, lambda x: x != el)
ているときに、私は驚いたことに気づきました。次のフォームを検討してください。
def method1(xs, el):
p = lambda x: x != el
return [x for x in xs if p(x)]
def method2(xs, el):
return [x for x in xs if (lambda y: y != el)(x)]
Pythonがラムダを1回だけビルドし、それを一時変数に格納して、両方のフォームがほぼ同様に機能するようにすることを期待します。名前の検索が原因で、それでもmethod1
パフォーマンスが低下する可能性があります。
しかし、私がそれらをベンチマークしたとき、それはmethod2
一貫してより悪いパフォーマンスであることがわかりましたmethod1
。どうしてこれなの?反復ごとにラムダを再構築していますか?
私のベンチマークスクリプト(別のモジュールにあり、とを含むことを期待しmethods
ています)は次のとおりです。method1
method2
import math, timeit
def bench(n,rho,z):
pre = """\
import random
from methods import %(method)s
x = [(random.randint(0,%(domain)i)) for r in xrange(%(size)i)]
el = x[0]\
"""
def testMethod(m):
mod = pre % { 'method': m, 'domain': int(math.ceil(n / rho)), 'size': n }
return timeit.timeit("%s(x, el)" % m, mod, number = z)/(z * n)
print "Testing", n, rho, z
return tuple(testMethod(m) for m in ("method1", "method2"))
n = 31
min_size, max_size = 10.0**1, 10.0**4
size_base = math.pow(max_size / min_size, 1.0/(n-1))
# size_default = 10**3
#min_sel, max_sel = 0.001, 1.0
#sel_base = math.pow(max_sel / min_sel, 1.0/(n-1))
sel_default = 0.001
tests = [bench(int(min_size*size_base**x), sel_default, 100) for x in xrange(n)]
#tests = [bench(size_default, min_sel*sel_base**x, 100) for x in xrange(n)]
def median(x):
x = list(sorted(x))
mi = int(len(x)/2)
if n % 2 == 0:
return x[mi]
else:
return (x[mi] + x[mi+1])/2
def madAndMedian(x):
meh = median(x)
return meh, median([abs(xx - meh) for xx in x])
for z in zip(*tests):
print madAndMedian(z)