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函数的 被收集到 alist中,在函数内部构建列表是否更有效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 回答