好吧,这里没有花哨的 itertools 或类似的东西,只是使用简单的循环避免递归和生成器的开销:
def for_loop(filters, tuples):
for f in filters:
tuples = filter(f, tuples)
if not tuples:
return tuples
return tuples
这是一个有点脏的基准:
import datetime
from itertools import ifilter
from timeit import Timer
def f1(t): return t[3]<10
def f2(t): return t[0]!=1
def f3(t): return t[1] in ("lisa","eric")
def f4(t): return t[3]>2
def original(filters,tuples):
if filters and tuples:
return original(filters,filter(filters.pop(),tuples))
else:
return tuples
def filter_lambda_all(filters, tuples):
return filter(lambda t: all(f(t) for f in filters), tuples)
def loop(filters, tuples):
while filters and tuples:
f = filters[0]
del filters[0]
tuples = filter(f, tuples)
return tuples
def pop_loop(filters, tuples):
while filters and tuples:
tuples = filter(filters.pop(), tuples)
return tuples
def for_loop(filters, tuples):
for f in filters:
tuples = filter(f, tuples)
if not tuples:
return tuples
return tuples
def with_ifilter(filters, tuples):
for f in filters:
tuples = ifilter(f, tuples)
return tuples
_filters = [f1, f2, f3, f4]
def time(f):
def t():
return [ (0,'tom','...',8),
(1,'john','...',17),
(2,'lisa','...',1),
(3,'eric','...',18)
]*1000
for i in xrange(4):
list(f(_filters[i:] * 15,t()))
if __name__=='__main__':
for f in (original,filter_lambda_all,loop,pop_loop,with_ifilter,for_loop):
t = Timer(lambda: time(f))
d = t.timeit(number=400)
print f.__name__, d
结果:
原始 7.23815271085
filter_lambda_all 14.1629812265
loop 7.23445844453
pop_loop 7.3084566637
with_ifilter 9.2767674205
for_loop 7.02854999945