Come posso (facilmente) prendere una stringa come "sin(x)*x^2"
che potrebbe essere immessa da un utente in fase di esecuzione e produrre una funzione Python che potrebbe essere valutata per qualsiasi valore di x
?Analisi delle equazioni in Python
risposta
Il compilatore interno di Python può analizzarlo, se si utilizza la notazione Python.
Se cambi leggermente la notazione, sarai più felice.
import compiler
eq= "sin(x)*x**2"
ast= compiler.parse(eq)
Si ottiene un albero di sintassi astratto con cui si può lavorare.
Sage è inteso come sostituzione MATLAB e in intro videos è dimostrato come vengono gestiti i casi simili. Sembrano supportare una vasta gamma di approcci. Dato che il codice è open source, puoi sfogliare e vedere di persona come gli autori gestiscono tali casi.
f = parser.parse('sin(x)*x^2').to_pyfunc()
Dove parser
potrebbe essere definito utilizzando PLY, pyparsing, tokenizzatore incorporata, parser, ast.
Non utilizzare eval
per l'input dell'utente.
"eval' sull'input dell'utente è davvero negativo. – igaurav
Per enfatizzare il consiglio di J.F. Sebastian, le soluzioni "eval" e persino quelle del "compilatore" possono essere aperte a sottili buchi di sicurezza. Quanto è affidabile l'input? Con 'compiler' puoi almeno filtrare cose come getattr lookup da AST, ma ho trovato che è più facile usare PLY o pyparsing per questo genere di cose piuttosto che garantire il risultato di lasciare che Python aiuti.
Inoltre, "compilatore" è maldestro e difficile da utilizzare. È deprecato e rimosso in 3.0. Dovresti usare il modulo 'ast' (aggiunto in 2.6, disponibile in 2.5 come '_ast').
In accordo con vartec. Vorrei usare SymPy - in particolare la funzione lambdify dovrebbe fare esattamente quello che vuoi.
Vedi: http://showmedo.com/videotutorials/video?name=7200080&fromSeriesID=720
per una bella spiegazione di questo.
migliori auguri,
Si prega di includere tutte le informazioni rilevanti nel post stesso, * "Ecco un link a un video che risponde alla domanda" * non è una buona risposta. –
pyparsing potrebbe fare ciò che si vuole (http://pyparsing.wikispaces.com/), soprattutto se le stringhe sono da una fonte non attendibile.
Vedere anche http://pyparsing.wikispaces.com/file/view/fourFn.py per un calcolatore abbastanza completo con esso incorporato.
È possibile utilizzare Python parser
:
import parser
formula = "sin(x)*x**2"
code = parser.expr(formula).compile()
from math import sin
x = 10
print eval(code)
Si comporta meglio di pura eval
e, naturalmente, evita l'iniezione di codice!
Una cosa importante da notare è che l'uso puro di 'eval()' sull'input dell'utente può essere [** molto pericoloso **] (https://stackoverflow.com/questions/1832940/is-using-eval-in-python -a-bad-pratica/1832957 # 1832957). –
Come si evita l'iniezione di codice? – devxeq
@devxeq Voglio dire che non accetterà cose come 'formula =" os.system ('formato C:') "' :) – Don
È possibile aggiungere un codice di esempio su come utilizzare la funzione derivata? – Don
@Don: non è necessario utilizzare l'albero di sintassi. Usa la funzione originale. 'eval (" sin (x) * x ** 2 ")' dopo aver impostato 'x' e usando' dall'importazione matematica * '. –
eval() funziona, ma la risposta in realtà non risolve il problema :( –