pythonでリスト内包表記を行うためのより良い方法はどれですか(計算時間とCPUサイクルの観点から)。例(1)では、値f(r)は各反復で評価されますか、それとも1回評価されてキャッシュされますか?
y = [x*f(r) for x in xlist]
c = f(r)
y = [x*c for x in xlist]
どこ
def f(r):
... some arbitrary function ...
Pythonコンパイラは関数に副作用があるかどうかわからないため、要素ごとに呼び出されるため、おそらく後者を選択します。
反復ごとに評価されます。これを見てください:
>>> def f():
... print("func")
...
>>> [f() for i in range(4)]
func
func
func
func
[None, None, None, None]
あなたが言うように、f()に副作用がない場合、戻り値を変数に格納し、代わりにその変数を使用する方がはるかに高速なソリューションです。
簡単に見つける方法は次のとおりです。
>>> def f():
... print "called"
... return 1
...
>>> [1+f() for x in xrange(5)]
called
called
called
called
called
[2, 2, 2, 2, 2]
そうです、関数が毎回同じになる場合は、リスト内包表記の外で一度呼び出す方がよいでしょう。
関数f
はすべての要素に対して呼び出されます。
コンパイラー/インタープリターが関数を何度も呼び出す必要がないと判断するのは非常に複雑です。その場合、関数が何度も呼び出される可能性が非常に高くなります。したがって、2番目のソリューションを使用することが常に最良のソリューションです。
関数の実行時間は名前のルックアップと比較して重要であり、関数が何度も呼び出され、毎回同じ値が期待される場合、値のキャッシュは許容できると見なされます。
Pythonはおそらく1回または何度もそれを自由に行うことができます。観察された動作に依存するかどうかはわかりません。次のバージョンで変更される可能性があります。
関数が1回だけ呼び出されるようにすることが重要な場合は、自分で呼び出して結果を保存してください。