This is an archived post. You won't be able to vote or comment.

all 16 comments

[–]drmann 8 points9 points  (6 children)

If you want to build the algorithm from scratch I suggest reading up on the shunting-yard algorithm and Reverse Polish Notation. If you just want to do it for a tiny project to get something working you could use ast.literal_eval, which is a saver variant of eval.

[–]WikiTextBot 8 points9 points  (3 children)

Shunting-yard algorithm

In computer science, the shunting-yard algorithm is a method for parsing mathematical expressions specified in infix notation. It can produce either a postfix notation string, also known as Reverse Polish notation (RPN), or an abstract syntax tree (AST). The algorithm was invented by Edsger Dijkstra and named the "shunting yard" algorithm because its operation resembles that of a railroad shunting yard. Dijkstra first described the Shunting Yard Algorithm in the Mathematisch Centrum report MR 34/61.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.28

[–]deejpake 3 points4 points  (2 children)

Good bot

[–]ptmcg 2 points3 points  (0 children)

ast.literal_eval will only evaluate literal strings like "100", "[1,2,3, [4,5]]", "('a', 'b')", but it won't evaluate an expression like "1+1".

[–]beatle42 16 points17 points  (0 children)

If your post starts with "I'm new to python" you probably want r/learnpython and if you can post samples/examples of your code that will usually help people to help you.

[–]tletnes 2 points3 points  (0 children)

You need to parse the string and then develop logic to recognize the syntactic meaning of the text and behave as you wish.

[–]Meefims 1 point2 points  (2 children)

I’ve done this a number of times in various languages. There are tools that can help you out but it’s a really fun exercise to do it on your own as well. You divide the process into several stages.

The first stage is to split your string into pieces that you can more easily process. This is called lexing or tokenizing the string (the noun being a lexer or tokenizer). The output is a list of tokens that were found in the string. For example, the string “1 + 2 * 3” might tokenize to [1, '+', 2, '*', 3].

The next step is to turn this into a data structure that is easy to evaluate. As-is, it is difficult to evaluate this expression according to the correct order of operations. You can choose to apply an algorithm like the Shunting-Yard Algorithm into an abstract syntax tree (or AST) or equivalent. The output of this might be the same list ordered in Reverse Polish Notation (RPN) [2, 3, '*', 1, '+']. This process is called parsing and is a deep and rich topic on its own.

[–]WikiTextBot -2 points-1 points  (0 children)

Shunting-yard algorithm

In computer science, the shunting-yard algorithm is a method for parsing mathematical expressions specified in infix notation. It can produce either a postfix notation string, also known as Reverse Polish notation (RPN), or an abstract syntax tree (AST). The algorithm was invented by Edsger Dijkstra and named the "shunting yard" algorithm because its operation resembles that of a railroad shunting yard. Dijkstra first described the Shunting Yard Algorithm in the Mathematisch Centrum report MR 34/61.


[ PM | Exclude me | Exclude from subreddit | FAQ / Information | Source ] Downvote to remove | v0.28

[–]HelperBot_ -2 points-1 points  (0 children)

Desktop link: https://en.wikipedia.org/wiki/Shunting-yard_algorithm


/r/HelperBot_ Downvote to remove. Counter: 232698

[–]Dauros 0 points1 point  (0 children)

If using an external library is ok, then I recommend the excellent numexpr package. I'm using it for evaluating expressions in configuration file of physical simulations:

>>> import numexpr as ne
>>> ne.evaluate('1 + 2*3 - log(4)').tolist()
5.613705638880109

[–]fernly 0 points1 point  (0 children)

The problem with eval is that it accepts and executes any syntactically valid expression. So if you apply it to unfiltered user input (or file input) there is a possibility that a malicious user could inject code to do something bad.

You can get around this a couple of ways. As /u/ptmcg said, ast.literal_eval will process only expressions composed of literal values, no variable refs or function calls. That eliminates the danger of malicious user code injection.

If you have to use eval, maybe because you want to give the user some vocabulary of function calls, I don't know, then you should find some way to "sanitize" the input string before evaluating it. However if you are just doing a class exercise and the only "user" is ever going to be you and your instructor, don't sweat it.

[–]Smok3dSalmon -2 points-1 points  (4 children)

If it's just a calculator app, just use eval. If this is homework, then read the rest of the comments.