2

特定の制約のあるものをランダムに生成する必要があることがよくあります。多くの場合、生成時に制約を無視し、後でそれらが満たされているかどうかを確認し、そうでない場合はプロセスをやり直す方が迅速です。キーワードが欠けてdo、私は通常書く

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

同じコード行が 2 回あるので、これは少し醜いです。私が本当に欲しいのは、次のような構造です

r = random_stuff() until meets_condition(r)

2.5 で導入された三項演算子に似ています。

a = b if condition else c

ここでの条件は、ステートメントの左側が実行される前に評価されます。while-constructs 固有の非 Python の醜さを改善する設計パターン (Python 2.7 で動作するはず) の提案はありますか?

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

あなたのアイデアは悪くありませんが、新しいキーワードuntilではなく、むしろ好きです

a = (<expression> while <condition>)

ジェネレータ式のアイデアを拡張します。

それらは存在しないため、役に立ちません。


しかし、使用できるのはセンチネルのiter機能です。

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

random_stuff()数値、文字列など、特定の種類の値のみを返すことが確実な場合は、他の値をセンチネルとして使用できます。特に、Nonenever が発生しない場合は、これを使用して、never-end ジェネレーターを作成します。

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

博士が注文したのはシンタックス シュガーなのだろうか?このようなことができます。

find_condition で kw 引数を処理するのが面倒でした。あなたはあなたが支払うものを手に入れます: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 に答える
0
while not meets_condition(random_stuff()): pass

実際に が必要な場合はrandom_stuff()、副作用として別の場所に保存できます (たとえば、クラスrandom_stuff__call__メソッドを作成します)。

于 2011-11-10T13:56:09.500 に答える