Pythonはパラメータを遅延評価しません。
dict.get
コールに渡されるデフォルト値は、dict.get
を呼び出す前に評価されます。
したがって、デフォルト値は再帰呼び出しを持ち、条件が決して満たされないため、無限再帰を行います。
あなたは、Pythonの関数に渡されるすべてのパラメータが評価されますので、キー0
は、辞書に存在しているにもかかわらず、getter
が実際dict.get
前に、また呼び出され、このプログラム
>>> def getter():
... print("getter called")
... return 0
...
>>> {0: 1}.get(0, getter())
getter called
1
で、これを確認することができます作成されます。
あなたがしたいすべてが値がすでに評価されたときに、複数の再帰的な評価を避けるためであれば、あなたはfunctools.lru_cache
を使用し、あなたは、Python 3.2以上
に
>>> @functools.lru_cache()
... def fact(n):
... print("fact called with {}".format(n))
... if n == 0:
... return 1
... return n * fact(n-1)
...
>>> fact(3)
fact called with 3
fact called with 2
fact called with 1
fact called with 0
6
>>> fact(4)
fact called with 4
24
を使用している場合、このデコレータは、単純にキャッシュします渡されたパラメータの結果が返され、同じ呼び出しが再度行われた場合、キャッシュから値が返されます。
あなたが仕事にカスタムキャッシュ機能を修正したい場合は、関数が呼び出されるたびに、それが作成されないように、関数の外look_up
を定義する必要があります。
>>> look_up = {0: 1}
>>> def fact(n):
... if n not in look_up:
... print("recursing when n is {}".format(n))
... look_up[n] = n * fact(n - 1)
... return look_up[n]
...
>>> fact(3)
recursing when n is 3
recursing when n is 2
recursing when n is 1
6
>>> fact(4)
recursing when n is 4
24
>>> fact(4)
24
そうでなければ、ああ、私はそれを得るこの
>>> def fact(n, look_up={0: 1}):
... if n not in look_up:
... print("recursing when n is {}".format(n))
... look_up[n] = n * fact(n - 1)
... return look_up[n]
のように、デフォルトのパラメータを使用することができます。したがって、 'default ='引数は最初の条件が満たされても評価されます。少し直感的ではないようですが、少なくとも私の問題は解決されています。ありがとう! – shooqie
@shooqie実際には、.get関数自体を呼び出す前に、Pythonは渡される実際の値を知っている必要があります。したがって、渡されたすべての式をパラメーターとして評価します。あなたのケースでは、式の1つが再帰呼び出しになり、単に '.get'を呼び出す前にそれを行います。 – thefourtheye
@shooqie関数型プログラミングのバックグラウンドはありますか?命令的な観点からは、関数を呼び出す前にすべての引数を評価する必要があります。 – Jasper