2012-04-29 2 views
1

私はODEソルバを書くことでPythonを学び始めています。私は、1つまたは複数の可変入力関数を透過的に扱いたいと思います。ここではオイラーの方法の一の工程のための私のコードは次のとおりです。数値型を一意のシーケンスとして扱う(またはその逆)

def euler(h, t, y, f): 
    return (y + h*f for y,f in zip(y,f(t,y))) 

は今、私は2つの機能、このようなf1f2定義:私はそれらをテストする場合

def f1(t,y): 
    return -2*t*y 

def f2(t,y): 
    x, y = y #is rebinding usually ok, or confusing? 
    return (x - t*y, y + x/t) 

を、それが

を何が起こるか(明らかに)です
>>> list(euler(0.01, 1, (1,2), f2)) 
[0.99, 2.03] 
>>> list(euler(0.01, 1, 1, f1)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in euler 
TypeError: zip argument #1 must support iteration 

与えられた関数が1つまたは複数の変数で動作していても、それを行うためのクールな方法が見つからない場合は、ソルバーが透過的に処理したいと思います。私が見つけた方法は

import operator as op 
def euler(h, t, y, f): 
    if op.isNumberType(y): 
     return (y + h*f(t,y),) 
    return (y + h*f for y,f in zip(y,f(t,y))) 

だった。しかし、今、私は、フロートに合格し、反復可能なので、list(euler(...))はsuceedでき戻りました。しかし、例えばf(t,euler(...))と呼ぶことはできません。

プリミティブ型としてシングルトンシーケンスを処理する方法、またはエンドレスチェックを行わずにシングルトンシーケンスとしてプリミティブを処理する方法はありますか? 「エンドレスチェック」とは、私のコード全体ではなく、ちょうどいくつかの場所でチェックしなければならないということです。または私はそれを吸うとf(t,y)は、数値の代わりにシーケンスを期待するか?

ご協力ありがとうございました。また、コーディングに関するヒントも歓迎します。

答えて

1

f(t、y)はシーケンスのみを使用するのは非常に簡単です:

def euler(h, t, y, f): 
    return (y + h*v for y,v in zip(y,f(t,y))) 

def f1(t,status): 
    x, = status 
    return -2*t*x, 

def f2(t,status): 
    x, y = status 
    return x - t*y, y + x/t 


print list(euler(0.01, 1, (1,2), f2)) 
print list(euler(0.01, 1, (1,), f1)) 
+0

あなたの答えは私のものとどう違うのですか? – Abhijit

+0

f1にxの後にカンマがあります。 – HYRY

+0

私は@ HYRYのベストが気に入っています。あなたの答えはありがとうございました。 –

1

ユーラー関数では、TypeErrorを捕まえてリストにカプセル化して再試行することができます。

+0

'try ... catch'は' if'より優先されますか? Javaでは(ええ、「JavaはPythonではありません」)、例外的な条件でのみ例外を使用することがベストプラクティスです。 –

+0

はい、「ダックタイピング」を参照すると詳細が得られます。 –

1

一つの可能​​な解決策は、

def euler(h, t, y, f): 
    if isinstance(y,collections.Iterable): 
     return (y + h*f for y,f in zip(y,f(t,y))) 
    else: 
     return (y+h*f(t,y),) 

別の解決策は、

def f1(t,y): 
    return (-2*t*y[0],) 

としてあなたの1次元の関数を記述して、次のよう

にオイラーを呼び出すことで、次のようにあなたのオイラー関数を記述することです
list(euler(0.01, 1, (1,), f1)) 
関連する問題