Python - Évaluer expression mathématique à l'intérieur de la chaîne
J'ai une question concernant l'évaluation de l'expression mathématique à l'intérieur d'une chaîne.
Par exemple, pour ma chaîne est la suivante:
my_str='I have 6 * (2 + 3) apples'
Je me demande comment l'évaluer cette chaîne et obtenir le résultat suivant:
'I have 30 apples'
Est la toute façon de le faire?
Merci d'avance.
P. S. python eval
fonction n'est pas utile dans ce cas. Il a soulevé une erreur, lorsque vous essayez d'évaluer avec le eval
fonction.
- Est-ce devoirs?
- stackoverflow.com/questions/2371436/...
- pas vraiment sur le point, comme ceci (à la différence qu') exige de les jeter non-math parties de la chaîne.
- Pourriez-vous utiliser
'I have {{ 6 * (2 + 3) }} apples'
comme un format d'entrée? - cela pourrait bien fonctionner avec un bon remplacement pour le
eval()
fonction: codepad.org/QOhSpWzH
Vous devez vous connecter pour publier un commentaire.
Voici ma tentative:
Notes:
C'est très simple, il n'a pas affaire à des équations complexes - comme ceux avec racine carrée, pi, etc. mais je crois que c'est dans l'esprit de ce que la question est après. Pour un vraiment robuste réponse voir la question posté par jeffery_the_wind; mais je crois que c'est peut-être exagéré pour ce cas simpliste.
Il est parfois préférable de simplifier la question plutôt que de venir avec des solutions. Vous pouvez simplifier le problème en faisant votre code sera fourni comme ce
De cette façon, vous pouvez l'analyser à l'aide d'une simple regex et eval ce qui est à l'intérieur. Sinon, vous êtes dans beaucoup de complexité.
C'est un très épineux problème qui est sans doute à peu près impossible à résoudre en général. Cependant, voici une façon simple de s'attaquer au problème, qui travaille avec l'exemple de l'entrée.
*étape 1-désinfecter l'entrée. C'est la partie la plus difficile à faire en général. Fondamentalement, vous avez besoin d'un moyen de tirer une seule expression mathématique de la chaîne sans déformation d'elle. Ici une simple regex fonctionne:
*étape 2-évaluer à l'aide de
eval
:*étape 3-arrière substitut
eval
.eval
abus, alors ce n'est paseval
abus (à quel point, il ne devrait pas être supprimée de la langue complètement?). Je pense que ceci est un bon endroit pour utilisereval
étant donné que le problème est limité suffisant pour analyser l'évaluation de l'expression de la chaîne d'entrée.eval
ne doivent pas être placés bien en vue (c'est à dire dans l'espace de noms global). Je connais des cas d'utilisation pourcompile
etexec
(et ils sont significativement différents de ce, dans ce qu'ils contrôlent la chaîne d'entrée de 100% et l'on sait ce qu'il va faire). Je n'ai pas encore rencontre un bon cas d'utilisation deeval
-- lorsque vous souhaitez évaluer une expression mathématique, écrire une manœuvre de triage de l'évaluateur ou de quelque chose. Si vous souhaitez exécuter du code Python, utilisezexec
parce que c'est moins restreint. Je n'ai pas l'évitereval
pour la correction, mais de ne pas mélanger les code avec les données. (Vis de l'lisp gars qui disent code de données).'6 * ( 2 + 3 )'
n'est pas le code. C'est une chaîne. Nous n'essayons pas de modifier le flux de programme ou quoi que ce soit...*
en reStructuredText est juste un personnage et non une majoration de construire). Et oui,6 * ( 2 + 3 )
est une chaîne de caractères, et non pas une expression Python. C'est exactement pourquoi je m'oppose à la passant àeval
. En outre, SY n'est pas très difficile à mettre en œuvre étant donné les détails des descriptions de celui-ci (je l'ai fait moi-même), et testé facilement. Il y a une limite raisonnable sur ce qui peut arriver avec une fonction comme ça, ou la plupart des autres fonctions. Aveceval
etc., la seule limite est celle de Python.eval
la seule limite est celle de Python" n'est vrai que pour un nueval
. Si vous passez un globals dictionnaire, vous limitez l'espace de noms quieval
a accès à l'utilisation et (autant que je sache), vous pouvez même l'utiliser en toute sécurité (comme je l'ai démontré dans ma réponse). Mais de toute façon ...Merci à tous pour votre aide. En fait, mon exemple fourni est très simple par rapport à ce que j'ai dans la tâche réelle. J'ai lu ces chaîne à partir d'un fichier et qu'il est parfois pouvez avoir vue comme ceci:
Équation mathématique sont simples, mais peuvent se produit de nombreuses fois dans une chaîne de caractères, et doivent être évalués séparément.
Donc j'écris un exemple de code, qui est en mesure de gérer ce cas de figure:
Peut-être qu'il n'est pas bon, mais de résoudre le problème:
Pour une solution sans l'utilisation d'eval, voici ce que je ferais. Commencez par trouver toutes les expressions mathématiques dans la chaîne, qui va me définir comme une chaîne de caractères qui contient des espaces, des parenthèses, des nombres et des opérations, puis d'en extraire les matchs qui sont tous les espaces:
Ensuite, évaluer les expressions à l'aide de la
NumericStringParser
classe de cette question, qui utilise pyparsing:Alors, de remplacer les résultats dans l'expression, de tri inverse l'expression de l'indice de départ et remettez-les dans la chaîne d'origine:
Mon option:
[Je sais c'est une vieille question, mais il est intéressant de souligner de nouvelles solutions comme ils pop up]
Depuis python3.6, cette capacité est maintenant construit dans la langue, inventé "f-chaînes".
Voir: PEP 498 -- Chaîne Littérale de l'Interpolation
Par exemple (notez le
f
préfixe):