2017-06-26 9 views
1

私の質問への回答が既にある場合はお詫びします。私はしばらくの間、スタックのオーバーフローを検索しましたが、私が使用できるものは何も見つかりませんでした。Pythonのインクリメント関数の名前

私は現在、クラスを作成する方法を学習しています。明示的なRunge-Kuttaメソッド1-4のクラスを作成しました。クラス名は「RK_1」、「RK_2」、「RK_3」、「RK_4」です。私のコードをテストするために、私はLegendre微分方程式を解くことにしました。私はこれもまた、「Legendre」と呼ばれるクラスを作成しました。

私はこの問題を解決したかったので、特定のRKスキームを使用してルジャンドルの問題を解決する関数を書きました。私は私のRKスキームのそれぞれのためにこれをやってみたかったので、私はしかし、私はこれを行うための簡単な方法がなければならない実現

def solve_Legendre_1(p,Tmax,init,dt=0.001): 

    f  = Legendre(p) 
    solver = RK_1(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

def solve_Legendre_2(p,Tmax,init,dt=0.001): 

    f  = Legendre(p) 
    solver = RK_2(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

def solve_Legendre_3(p,Tmax,init,dt=0.001): 

    f  = Legendre(p) 
    solver = RK_3(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

def solve_Legendre_4(p,Tmax,init,dt=0.001): 

    f  = Legendre(p) 
    solver = RK_4(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

すなわち、同じ機能を4回を書きました。だから、私は

for j in range(4): 
    def solve_Legendre_%s(p,Tmax,init,dt=0.001) % (j+1): 

     f  = Legendre(p) 
     solver = RK_%s(init,f) % (j+1) 

     while solver.now() < Tmax: 
      solver(dt) 

     return solver.state() 

のように、何かを関数の名前を変更するにはループとstr.format()を使用して、それはそれに対応するRK方式で取るために得ることができるかもしれないと思ったが、これは明らかにしません作業。私はこれにどのようにアプローチすべきか誰にも分かりますか?

ありがとうございました。

+10

は、なぜあなたは、同じ機能を4回書いていますか...?その関数に可変性がある場合は、その内部に変数を使用します*。同じコードを繰り返さず、繰り返しコードの自動生成を開始しないことが最も確実です。 – deceze

+1

@deceze夜は非常に遅いので、私はまっすぐ考えることや愚かなことをしているわけではありません。ご協力いただきありがとうございます。 – Mattos

答えて

7

あなたは、単に他の機能重複を避けるために、パラメータとしてでRK_n()関数を渡すことができます。

def solve_Legendre(p,Tmax,init,dt=0.001, RK=RK_1): 

    f  = Legendre(p) 
    solver = RK(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

を、あなたがしたい場合は、事前にその最後のパラメータをバインドすることができます。

import functools 
solve_Legendre_1 = functools.partial(solve_Legendre, RK=RK_1) 
solve_Legendre_2 = functools.partial(solve_Legendre, RK=RK_2) 
... 
+1

私は本当に自分自身を考えていたはずです。ご協力いただきありがとうございます。 – Mattos

1

あなたは関数に数値、リスト、文字列などの「普通の」ものを与えるだけでなく、関数自体をパラメータとして使うこともできます:

>>> def test1(): 
    print(1) 

>>> def test2(): 
    print(2) 

>>> def solve_with_func(funcname): 
    funcname() 

>>> solve_with_func(test1) 
1 
>>> solve_with_func(test2) 
2 

このようにしてsolve_with_funcに同じロジックを使用して、実行される機能を簡単に交換することができます。

もちろんこの缶は関数のリストに拡張される:

>>> def execute_all(funclist): 
    for f in funclist: 
     f() 


>>> execute_all([test1, test2]) 
1 
2 
1

あなたの関数は、あなたは、単に追加の変数で渡すことができ、RK_x機能のみが異なります。これにより、コードの冗長性が最小限に抑えられます。

def solve_Legendre(RK_func, p,Tmax,init,dt=0.001): 

    f  = Legendre(p) 
    solver = RK_func(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

これで、グローバルをクエリできます。 globals()関数は、グローバルスコープで定義されたすべてのオブジェクトが識別子でキーされたマップを返します。だから私の前の関数を使って書くことができます:

for j in range(4): 
    globals()['solve_Legendre_%d' % (j + 1)] = lambda *args, **kw_args: solve_Legendre(globals()['RK_%d' % (j + 1)], *args, **kw_args) 
+0

ありがとうございます。 globals()を使用するコードの2番目の部分は、まさに私が探していたものでした。とても有難い。 – Mattos

1

あなたにはパラメータを追加する必要があります。だから、すべてあなたのスキームを解決するための一つの機能を持っている:

def solve_Legendre(p,Tmax,init,dt=0.001, RK): 

    f  = Legendre(p) 
    solver = RK(init,f) 

    while solver.now() < Tmax: 
     solver(dt) 

    return solver.state() 

したい場合は、RKのデフォルト値を設定することができます。

def solve_Legendre(p,Tmax,init,dt=0.001, RK=RK_1): 
関連する問題