3

Python v2.7では、次のような関数がある場合:

def holes_between(intervals):
  # Compute the holes between the intervals, for example:
  #   given the intervals: ([ 8,  9] [14, 18] [19, 20] [23, 32] [34, 49])
  #     compute the holes: ([10, 13] [21, 22] [33, 33])
  prec = intervals[0][1] + 1 # Bootstrap the iteration
  for low, high in intervals[1:]:
    if prec <= low - 1:
      yield (prec, low - 1)
    prec = high + 1

holes = list(holes_between(intervals))

yield関数のはに収集されているので、関数list内にリストを作成するholes_between方が効率的ですか?もしそうなら、それはどのように最も効率的に行われるでしょうか?

4

2 に答える 2

3

ジェネレーター関数、リストを直接作成するよりも効率が悪い場合があります。

関数でリストを作成して、holes_between()それを返すことができます。

def holes_between(intervals):
    prec = intervals[0][1] + 1 # Bootstrap the iteration
    result = []
    for low, high in intervals[1:]:
        if prec <= low - 1:
            result.append((prec, low - 1))
        prec = high + 1
    return result

ただし、モジュールを使用して差異を測定してください。timeit

典型的な入力がある場合は、次の方法でテストします。

import timeit

def holes_between_list(intervals):
    prec = intervals[0][1] + 1 # Bootstrap the iteration
    result = []
    for low, high in intervals[1:]:
        if prec <= low - 1:
            result.append((prec, low - 1))
        prec = high + 1
    return result

def holes_between_generate(intervals):
    prec = intervals[0][1] + 1 # Bootstrap the iteration
    for low, high in intervals[1:]:
        if prec <= low - 1:
            yield (prec, low - 1)
        prec = high + 1

intervals = [ ... ] # fill in some test data

print 'As list:', timeit.timeit(
    'holes_between(intervals)',
    'from __main__ import intervals, holes_between_list as holes_between')

print 'Using a generator:', timeit.timeit(
    'list(holes_between(intervals))',
    'from __main__ import intervals, holes_between_generate as holes_between')

値が小さいほど、テストデータの処理が速くなります。

于 2013-02-27T17:47:33.567 に答える
0

一般に、遅延評価の柔軟性は、ジェネレーターを使用することで得られる可能性のあるマイナーなパフォーマンスの低下を上回ります。列挙可能なもののすべてが使用されていない場合、ジェネレーターアプローチの方がパフォーマンスが向上します。

たとえば、間隔間の穴のサイズの最大しきい値をチェックする関数が必要だとします。

def threshold(intervals, n):
    for low, high in holes_between(intervals):
        if (high - low + 1) >= n:
            return True
    return False

この場合、反復可能な間隔が大きいと、早い段階でしきい値を超えた場合に多くの作業を節約できる可能性があります。一般に、これらの種類の「早期復帰」関数のいずれも、ジェネレーターの恩恵を受けます。

これがコードの重要な部分であり、決定的なパフォーマンスの問題を測定した場合はholes_between、そうです。関数自体にリストを作成するように書き直すことができます。その場合は、関数のベンチマークを行って、実際に関数のパフォーマンスが向上したかどうかを確認してください。

于 2013-02-27T17:50:51.610 に答える