表达条件有界循环的更pythonic方式?

时间:2010-04-26 05:31:08

标签: coding-style 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用于我通常具有有限但未知长度的迭代器(并且谓词有时返回False)。

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)

答案 2 :(得分:1)

我从

开始
if limit is None: return

因为limitNone开头时没有任何事情发生(如果在迭代和predicate的计算中没有理想的副作用 - 如果有的话,那么,在这种情况下你可以做for i in xrange(10**5): predicate(i))。

如果limit不是None,那么您只想执行max(limit, 1)的{​​{1}}计算,这些计算是真的,因此predicate的{​​{1}} 1}}会做:

itertools.islice

答案 3 :(得分:1)

您应该删除嵌套的ifs:

if predicate(i) and not limit is None:
    ...

答案 4 :(得分:0)

你想要做什么似乎非常适合while循环:

def ello_bruce(limit=None):
    max = 10**5
    # if you consider 0 to be an invalid value for limit you can also do
    # if limit:
    if limit is None: 
        limit = max

    while max and limit:
        if predicate(i):
            limit -= 1
        max -=1

如果maxlimit达到零,则循环停止。

答案 5 :(得分:0)

庵。据我了解,predicate只是计算段,你完全忽略它的返回值,对吗?

这是另一种看法:

import itertools

def ello_bruce(limit=None):
    if limit is None:
        limiter= itertools.repeat(None)
    else:
        limiter= xrange(limit)

    # since predicate is a Python function
    # itertools looping won't be faster, so use plain for.
    # remember to replace the xrange(100000) with your own iterator
    for dummy in itertools.izip(xrange(100000), limiter):
        pass

另外,从return True的末尾删除不需要的predicate