2009-02-27 23 views
33

"sin(x)*x^2"などの文字列を実行時にユーザーが入力し、xの任意の値で評価できるPython関数を生成するにはどうしたらよいでしょうか?Pythonでの数式解析

答えて

46

Pythonの表記法を使用すると、Python独自の内部コンパイラがこれを解析できます。

表記を少し変更すると、より幸せになれます。

import compiler 
eq= "sin(x)*x**2" 
ast= compiler.parse(eq) 

あなたが作業できる抽象構文ツリーがあります。

+1

派生関数の使用方法に関するサンプルコードを追加できますか? – Don

+2

@Don:構文ツリーを使う必要はありません。オリジナルの関数を使用します。 'x'を設定し、' from math import * 'を使って 'eval(" sin(x)* x ** 2 ")'を実行します。 –

+1

eval()は動作しますが、答えは実際には問題を解決しません:( –

0

Sageはmatlabの置き換えを意図しており、intro videosではあなたのケースとどれほど類似しているかが実証されています。彼らは幅広いアプローチをサポートしているようです。コードはオープンソースなので、著者がそのようなケースをどのように処理するかを自分で閲覧して見ることができます。

parserはPLY、pyparsing、組み込みのトークナイザ、パーサ、ASTを使用して定義することができ
13
f = parser.parse('sin(x)*x^2').to_pyfunc() 

ユーザの入力にevalを使用しないでください。

+4

ユーザー入力の 'eval'は本当に悪いです。 – igaurav

2

J.F. Sebastianのアドバイスを強調するために、「eval」と「コンパイラ」ソリューションでさえ、微妙なセキュリティホールに開放することができます。入力はどのくらい信頼できるのですか? 'compiler'を使うと、少なくともASTのgetattrルックアップのようなものを除外することができますが、Pythonの助けを借りた結果を確保するよりもPLYやPyparsingを使う方が簡単です。

また、 'compiler'は使いにくく、使いにくいです。 3.0では推奨されなくなりました。 'ast'モジュール(2.6で追加、 '_ast'として2.5で利用可能)を使うべきです。

1

vartecと一致します。私はSymPyを使用します - 特にlambdify関数はあなたが望むものを正確に行うべきです。

参照:http://showmedo.com/videotutorials/video?name=7200080&fromSeriesID=720

本の非常に素晴らしい説明のために。

幸運を祈り、

+1

投稿に関連するすべての情報を含めてください。*「質問に答えたビデオへのリンクです」*は良い答えではありません。 –

22

あなたは、Python parserを使用することができます。

import parser 
formula = "sin(x)*x**2" 
code = parser.expr(formula).compile() 

from math import sin 
x = 10 
print eval(code) 

それはeval純粋なより良い行いと、当然のことながら、コードインジェクションを回避!

+5

注目すべき重要な点の1つは、ユーザーの入力に純粋な 'eval()'を使用すると[**非常に危険です**](https://stackoverflow.com/questions/1832940/is-using-eval-in-python -a-bad-practice/1832957#1832957)。 –

+0

これはコードインジェクションをどのように回避するのですか? – devxeq

+0

@devxeqこれは、 'formula =" os.system( 'format C:') "'のようなものを受け入れないことを意味します: – Don