在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
函数中构建列表是否更有效,如果是,那将如何完成?最有效率的?
答案 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
函数本身中构建列表。如果你这样做,一定要对功能进行基准测试,看看你是否真的让它表现得更好。