Разбор уравнений в Python

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

Ответов (7)

Решение

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

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

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

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

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

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

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

 f = parser.parse('sin(x)*x^2').to_pyfunc()

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

Не используйте eval для ввода пользователем.

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

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

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

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

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

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

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

import parser
from math import sin

formula = "sin(x)*x**2"
code = parser.expr(formula).compile()
x = 10
print(eval(code))

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