8

高階関数とラムダを使用すると、実行時間とメモリ効率が良くなりますか、それとも悪くなりますか?たとえば、リスト内のすべての数値を乗算するには:

nums = [1,2,3,4,5]
prod = 1
for n in nums:
    prod*=n

vs

prod2 = reduce(lambda x,y:x*y , nums)

HOFバージョンには、コード行が少ない/機能的なアプローチを使用していることを除いて、ループバージョンよりも優れていますか?

編集:

必要な評判がないため、これを回答として追加することはできません。@DSMによって提案されたように、timeitを使用してループとHOFアプローチのプロファイルを作成しました。

def test1():         
    s= """
    nums = [a for a in range(1,1001)] 
    prod = 1 
    for n in nums:
        prod*=n
    """            
    t = timeit.Timer(stmt=s)
    return t.repeat(repeat=10,number=100)    

def test2():
    s="""
    nums = [a for a in range(1,1001)]     
    prod2 = reduce(lambda x,y:x*y , nums)
    """
    t = timeit.Timer(stmt=s)
    return t.repeat(repeat=10,number=100) 

そしてこれが私の結果です:

Loop:
[0.08340786340144211, 0.07211491653462579, 0.07162720686361926, 0.06593182661083438, 0.06399049758613146, 0.06605228229559557, 0.06419744588664211, 0.0671893658461038, 0.06477527090075941, 0.06418023793167627]
test1 average: 0.0644778902685
HOF:
[0.0759414223099324, 0.07616920129277016, 0.07570730355421262, 0.07604965128984942, 0.07547092059389193, 0.07544737286604364, 0.075532959799953, 0.0755039779810629, 0.07567424616704144, 0.07542563650187661]
test2 average: 0.0754917512762

平均的なループアプローチでは、HOFを使用するよりも高速であるように思われます。

4

2 に答える 2

7

Higher-order functions can be very fast.

For example, map(ord, somebigstring) is much faster than the equivalent list comprehension [ord(c) for c in somebigstring]. The former wins for three reasons:

  • map() pre-sizes the result string to the length of somebigstring. In contrast, the list-comprehension must make many calls to realloc() as it grows.

  • map() only has to do one lookup for ord, first checking globals, then checking and finding it in builtins. The list comprehension has to repeat this work on every iteration.

  • The inner loop for map runs at C speed. The loop body for the list comprehension is a series of pure Python steps that each need to be dispatched or handled by the eval-loop.

Here are some timings to confirm the prediction:

>>> from timeit import Timer
>>> print min(Timer('map(ord, s)', 's="x"*10000').repeat(7, 1000))
0.808364152908
>>> print min(Timer('[ord(c) for c in s]', 's="x"*10000').repeat(7, 1000))
1.2946639061
于 2012-01-28T01:52:24.123 に答える
1

私の経験から、ループはあまりにも深く入れ子にされていない限り、非常に高速に実行できます。また、複雑で高度な数学演算を使用すると、単純な操作とループの単一レイヤーの場合、他の方法と同じくらい高速になる可能性があります。ループまたはループへのインデックスとして整数のみが使用されます。実際には、あなたが何をしているのかにも依存します

また、高次関数がループ プログラム バージョンと同じ数のループを生成し、少し遅くなる可能性もあります。念のため、両方の時間を計る必要があります。

于 2012-01-28T01:36:32.273 に答える