2

Peter NorvigのWebサイトで、次の質問に答えようとしている記事を見ていました(これは私の質問ではありませんが、Pythonで(テスト?結果:代替)と同等のことを実行できますか?」

これが彼がリストしたオプションの1つです。

def if_(test, result, alternative=None):
    "If test is true, 'do' result, else alternative. 'Do' means call if callable."
    if test:
        if callable(result): result = result()
        return result
    else:
        if callable(alternative): alternative = alternative()
        return alternative

そして、これが使用例です。

>>> fact = lambda n: if_(n <= 1, 1, lambda: n * fact(n-1))
>>> fact(6)
720

これがどのように機能するかは理解していますが(私は思う)、コードをいじっているだけで、上記の「fact」の定義の3番目の引数をn * fact(n-1)に変更するとどうなるかを確認することにしました。つまり、呼び出し不可能な式に変更します。それを実行すると、インタプリタは無限ループに入ります。なぜそれが起こっているのか、つまり、if_関数が受け取っているのと同じ式を返しているのかについてはかなり良い考えがあります。しかし、その表現のタイプは何ですか?ここで何が起こっているのですか?私は詳細な説明を探していませんが、私の理解に役立つかもしれないPythonの評価モデルへのいくつかのポインタを探しています。

ありがとう!

4

1 に答える 1

4

factに変更したときにループが終了しない理由は、最初に評価する必要があるためn * fact(n-1)ですn * fact(n-1)(の3番目の引数としてif)。factそれを評価することは、無限に、(それを止めるための基本的なケースがもはやないので)への別の呼び出しにつながります。

lambda以前は、の本体まで評価されない関数オブジェクト()を渡してifおり、その結果は。を介してチェックされてtestいました。

これは、関数の引数が関数に渡される前に評価される、先行評価として知られています(私は信じています)。遅延評価スキームでは、引数は関数本体で使用されるまで評価されません。

于 2010-04-26T19:44:16.770 に答える