9

Python で遊んでみると、次のコードが期待どおりに機能することがわかりました。

f = lambda S,b : (S if len(S)==b else f(S[1:],b))

リスト S から、S の長さが b に等しくなるまで、最初の要素を再帰的に削除します。たとえば、f([1,2,3,4,5,6],3) = [4,5,6] です。

しかし、驚いたことに、「b if c else a」(別名「c?b:a」) の代わりに「三項ハック」 [a,b][c] を使用する次のソリューションは機能しません。

g = lambda S,b : (g(S[1:],b),S)[len(S)==b]

これは最大再帰深度を超えます。

なぜこれが機能しないのですか?

(どちらも優れたコーディング スタイルの例ではないことはわかっていますが、それは今では重要ではありません。)

4

3 に答える 3

4

問題は三項演算子の仕組みに関連していると思います。三項演算子を使用すると、条件をチェックする前に両方の式が評価されます。

g = lambda S,b : (g(S[1:],b),S)[len(S)==b]

したがって、この場合g(S[1:],b)は if ステートメントに到達する前に評価されます。

関数がある場合、同じケースである基本ケースはありませんg(S[1:],b)

def func(S, b)
    return func(S[1:],)

func(S,b)
#output: error - exceed maximum recursion depth

S[1:] は空になるポイントに到達し、空の場合は空のリストを返します。

空のリストに関する小さな例:

S = [0, 1]

S = S[1:]
# [1]

S = S[1:]
# [] # empty

S = S[1:]
# [] # also empty
于 2013-11-08T13:13:51.493 に答える
2

を実行すると、最初に が実行されA if C else B、次にまたはのいずれかが実行され (結果が返されます)、実行すると と の両方が実行され、次にが実行されます。これは、入力を出力してから返す関数を実行することで簡単に確認できます。C AB[B, A][C]AB Cp("A") if p("C") else p("B")[p("B"), p("A")][p("C")]pTrueFalse

したがって、最初のケースでS if len(S)==b else f(S[1:],b)は、条件が適用されない場合にのみ再帰呼び出しが実行されます。ただし、2 番目のケースでは、条件がテストされる前に実行され、再帰的に呼び出される関数でも同じことが無限に実行されます。

(実際にこれを使用するつもりはないので、これは重要ではないかもしれませんが、いずれにせよ: (1) どちらの関数にもケースの保護がないことに注意してくださいlen(S) < b。(2) S[-b:]、および ( 3)if/elseもちろん、using の方がはるかに読みやすいです。)

于 2013-11-08T13:17:47.357 に答える