Разбор уравнений в Python - PullRequest
35 голосов
/ 27 февраля 2009

Как я могу (легко) взять строку, такую ​​как "sin(x)*x^2", которая может быть введена пользователем во время выполнения, и создать функцию Python, которая может быть оценена для любого значения x?

Ответы [ 7 ]

47 голосов
/ 27 февраля 2009

Собственный внутренний компилятор Python может это проанализировать, если вы используете нотацию Python.

Если вы немного измените обозначение, вы станете счастливее.

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

Вы получаете абстрактное синтаксическое дерево, с которым вы можете работать.

29 голосов
/ 09 мая 2011

Вы можете использовать Python parser:

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

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

Он работает лучше, чем чистый eval и, конечно, избегает внедрения кода!

14 голосов
/ 27 февраля 2009
 f = parser.parse('sin(x)*x^2').to_pyfunc()

Где parser может быть определено с использованием PLY, pyparsing, встроенного токенизатора, парсера, аст.

Не используйте eval при вводе данных пользователем.

7 голосов
/ 29 марта 2010

pyparsing может делать то, что вы хотите (http://pyparsing.wikispaces.com/), особенно если строки получены из ненадежного источника.

См. Также http://pyparsing.wikispaces.com/file/view/fourFn.py для довольно полнофункционального калькулятора, построенного с ним.

2 голосов
/ 27 февраля 2009

Чтобы подчеркнуть совет Дж. Ф. Себастьяна, решения 'eval' и даже 'компилятор' могут быть открыты для тонких дыр в безопасности. Насколько заслуживает доверия вход? С помощью 'compiler' вы можете, по крайней мере, отфильтровать такие вещи, как поиск getattr из AST, но я обнаружил, что проще использовать PLY или pyparsing для такого рода вещей, чем обеспечить результат помощи Python.

Кроме того, «компилятор» неуклюж и труден в использовании. Это устарело и удалено в 3.0. Вы должны использовать модуль 'ast' (добавлен в 2.6, доступен в 2.5 как '_ast').

1 голос
/ 29 марта 2010

По согласованию с vartec. Я бы использовал SymPy - в частности, функция lambdify должна делать именно то, что вы хотите.

См .: http://showmedo.com/videotutorials/video?name=7200080&fromSeriesID=720

за очень хорошее объяснение этого.

С наилучшими пожеланиями,

0 голосов
/ 27 февраля 2009

Sage предназначен для замены matlab, а в вступительных видеороликах показано, как обрабатываются случаи, подобные вашим Кажется, они поддерживают широкий спектр подходов. Так как код с открытым исходным кодом, вы можете просмотреть и сами убедиться, как авторы обрабатывают такие случаи.

...