2

我经常不得不随机生成具有某些约束的东西。在许多情况下,忽略生成中的约束会更快,然后检查它们是否满足,否则重做该过程。缺少do关键字,我通常会写

r = random_stuff()
while not meets_condition(r):
    r = random_stuff()

这有点难看,因为我有两次相同的代码行。我真正想要的是一个像

r = random_stuff() until meets_condition(r)

类似于 2.5 中引入的三元运算符:

a = b if condition else c

只是在执行语句的左侧之前评估了这里的条件。有没有人建议一种设计模式(应该在 Python 2.7 中工作)来补救while-constructs 内在的 unpythonic 丑陋?

4

5 回答 5

8
while True:
    r = random_stuff()
    if meets_condition(r):
        break

或者

condition = True
while condition:
    r = random_stuff()
    condition = not meets_condition(r)
于 2011-11-10T13:19:22.450 回答
1

你的想法不错——但不是用 new 关键字until,而是喜欢

a = (<expression> while <condition>)

扩展生成器表达式的思想。

由于它们不存在,因此对您没有帮助。


但是您可以使用的是带有哨兵的iter功能。

dummy_sentinel = object()
for r in iter(random_stuff, dummy_sentinel):
    if meets_condition(r): break

如果你可以确定你random_stuff()只返回某种类型的值,比如数字、字符串等,你可以把一些其他的值作为哨兵。特别是,当None永远不会发生时,请使用它,以便拥有一个永无止境的生成器。

for r in iter(random_stuff, None):
    if meets_condition(r): break

然后random_stuff()被调用,直到它满足条件。


更好的可能是

r = next(r for r in iter(random_stuff, None) if meets_condition(r))

这给了你第一个匹配的。

于 2011-11-10T13:50:42.723 回答
0
while not meets_condition(random_stuff()): pass

如果您确实需要,random_stuff()那么它可以作为副作用存储在其他地方(例如,创建一个类random_stuff__call__方法)。

于 2011-11-10T13:56:09.500 回答
0

也许语法糖是博士命令的?你可以做这样的事情。

我懒得在 find_condition 中处理 kw args。你得到你所支付的:D。

def find_condition(cond_mk, cond_ck, *args):
    """
    .. function:: find_condition(cond_mk, cond_ck) -> cond

       Create conditions by calling cond_mk until one is found that passes
       the condition check, cond_ck.  Once cond_ck returns True, iteration 
       over cond_mk stops and the last value processed is returned.

       ** WARNING **
       This function could loop infinitely.

       ``cond_mk`` - callable that creates a condition.  It's return value is
       passed to cond_ck for verification.

       ``cond_ck`` - callable that checks the return value of cond_mk.  

       ``args`` - any arguments to pass to cond_mk should be supplied here.
    """
    v = cond_mk(*args)
    while not cond_ck(v):
        v = cond_mk(*args)
    return v

# Test it out..
import random
random.seed()
print find_condition(random.randint, lambda x: x > 95, 1, 100)
于 2011-11-10T16:12:10.600 回答
0

好的,受@jaime 启发,我编写了以下装饰器:

def retry(condition):
    def deco_retry(f):
        def f_retry(*args, **kwargs):
            success = False
            while not success:
                result = f(*args, **kwargs)
                success = condition(result)
            return result
        return f_retry
    return deco_retry

现在,以下工作:

def condition(calue):    
    return value < .5

@retry(condition)
def random_stuff():
    return random.random()

print random_stuff()

此外,内联:

@retry(lambda x: x < .5)
def random_stuff():
    return random.random()

print random_stuff()

但是,重试现在绑定到该random_stuff()方法,该方法现在只能用于修饰它的条件。此外,它不适用于实例方法(如 中@retry(self.condition))。有什么想法可以规避吗?

于 2011-11-10T22:20:32.860 回答