Python可以使列表更高效吗?

时间:2013-02-27 17:44:16

标签: python python-2.7 list generator yield

在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函数中构建列表是否更有效,如果是,那将如何完成?最有效率的?

2 个答案:

答案 0 :(得分: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 module 衡量差异。

如果你有一些典型的输入,你可以用以下方法测试:

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')

较低的值是测试数据的方法

答案 1 :(得分:0)

一般来说,我会说,懒惰评估的灵活性超过了使用生成器可能获得的轻微性能损失。如果不使用所有可枚举的,则生成器方法将表现得更好。

例如,假设您想要一个函数来检查间隔之间的孔大小的最大阈值:

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

在这种情况下,如果可迭代的间隔很大,那么如果早期超过阈值,则可以节省大量工作。通常,这些“早期返回”功能中的任何一种都将从发电机中受益。

如果这是您的代码的关键部分,并且您已经测量了明确的性能问题,那么是的,您可以重写它以在holes_between函数本身中构建列表。如果你这样做,一定要对功能进行基准测试,看看你是否真的让它表现得更好。