11

私はPythonが初めてです。ルンゲ・クッタ法を使用して一連の常微分方程式を数値的に積分するスクリプトを作成しています。ルンゲクッタ法は便利な数学的アルゴリズムであるため、独自の .py ファイル rk4.py に入れました。

def rk4(x,dt):
    k1=diff(x)*dt
    k2=diff(x+k1/2)*dt
    k3=diff(x+k2/2)*dt
    k4=diff(x+k3)*dt
    return x+(k1+2*k2+2*k3+k4)/6

このメソッドは、アルゴリズムを実行するためにユーザーが使用している一連の方程式を知る必要があるため、機能diff(x)に必要な導関数を rk4 に与える関数を呼び出します。方程式は使用によって変化するため、特定の問題を実行するスクリプトで diff() を定義する必要があります。この場合、問題は水銀の軌道なので、 と書きmercury.pyました。(これは最終的にどのようになるかではありませんが、私が何をしているのかを理解するために単純化しました。)

from rk4 import rk4
import numpy as np

def diff(x):
    return x

def mercury(u0,phi0,dphi):
    x=np.array([u0,phi0])
    dt=2
    x=rk4(x,dt)
    return x

mercury(1,1,2)

Mercury.py を実行すると、次のエラーが表示されます。

  File "PATH/mercury.py", line 10, in mercury
    x=rk4(x,dt)
  File "PATH/rk4.py", line 2, in rk4
    k1=diff(x)*dt
NameError: global name 'diff' is not defined

グローバル関数ではないためdiff()、rk4 を実行すると、diff について何もわかりません。明らかに、rk4 は小さなコードであり、その時点で使用しているスクリプトにそれを押し込むことができますが、ルンゲクッタ積分器は、NumPy で定義された配列と同様に、基本的な数学ツールであると思います。それを使用するすべてのスクリプト(多くの場合があります)で定義されている関数ではなく、呼び出される関数にすることは理にかなっています。しかし、特定の .py ファイルから特定の diff をインポートするように rk4.py に指示することもできません。これは、最初に必要な rk4 の一般性を台無しにするためです。

rk4 が呼び出されたときに diff を認識できるように、mercury.py のようなスクリプト内でグローバルに diff を定義する方法はありますか?

4

2 に答える 2

11

関数を引数として受け入れます。

def rk4(diff,  # accept an argument of the function to call
        x, dt)
    k1=diff(x)*dt
    k2=diff(x+k1/2)*dt
    k3=diff(x+k2/2)*dt
    k4=diff(x+k3)*dt
    return x+(k1+2*k2+2*k3+k4)/6

次に、を呼び出すときに、rk4実行する関数を渡すだけです。

from rk4 import rk4
import numpy as np

def diff(x):
    return x

def mercury(u0,phi0,dphi):
    x=np.array([u0,phi0])
    dt=2
    x=rk4(diff,  # here we send the function to rk4
          x, dt)
    return x
mercury(1,1,2)

クロージャ(周囲のコード)から取得するのではなく、引数としてmercury受け入れることも良い考えかもしれません。diff次に、通常どおりにそれを渡す必要があります。mercury最後の行のへの呼び出しは、を読み取りますmercury(diff, 1, 1, 2)

関数は、引数として使用したり、リストに保持したり、名前空間の名前に割り当てたりすることができるという意味で、Pythonでは「第一級市民」です(クラスやモジュールを含むほとんどすべてのものと同じです)。

于 2012-10-02T14:17:28.523 に答える
3

diffはすでにモジュール内のグローバルですmercury.py。ただし、それを使用するには、次のrk4.pyようにインポートする必要があります。

from mercury import diff

それがあなたの質問に対する直接的な答えです。

ただし、 @poorsod で提案されているようにdiff関数を渡すと、rk4はるかにエレガントになり、mercury.pyとの間の循環依存も回避されるrk4.pyため、そのようにすることをお勧めします。

于 2012-10-02T14:22:58.233 に答える