更具Python风格的有条件边界循环表达方法?
我有一个循环,它想要一直执行,直到耗尽或者达到用户指定的限制。我写的代码看起来不太好,但我找不到更优雅的写法;有没有更好的方法呢?
def ello_bruce(limit=None):
for i in xrange(10**5):
if predicate(i):
if not limit is None:
limit -= 1
if limit <= 0:
break
def predicate(i):
# lengthy computation
return True
哇,这个嵌套太复杂了!一定有更好的办法。为了举个例子,这里用到了xrange
,通常我会用一个长度有限但不确定的迭代器(而且有时候条件会返回假)。
6 个回答
1
我会从这个开始:
if limit is None: return
因为当limit
一开始是None
的时候,什么事情都不会发生(前提是迭代和计算predicate
的时候没有任何副作用——如果有副作用的话,你可以直接用for i in xrange(10**5): predicate(i)
来处理)。
如果limit
不是None
,那么你只想执行predicate
中为真的计算,次数是max(limit, 1)
,所以可以使用itertools.islice
和itertools.ifilter
来实现:
import itertools as it
def ello_bruce(limit=None):
if limit is None:
for i in xrange(10**5): predicate(i)
else:
for _ in it.islice(
it.ifilter(predicate, xrange(10**5),
max(limit, 1)): pass
2
我建议你好好看看 itertools 这个库。用这个库的话,我觉得你可以做到类似下面这样的事情...
# From the itertools examples
def tabulate(function, start=0):
return imap(function, count(start))
def take(n, iterable):
return list(islice(iterable, n))
# Then something like:
def ello_bruce(limit=None):
take(filter(tabulate(predicate)), limit)
11
也许像这样会稍微好一些:
from itertools import ifilter, islice
def ello_bruce(limit=None):
for i in islice(ifilter(predicate, xrange(10**5)), limit):
# do whatever you want with i here