7

I have a variable that is function = '(2*1)+3'. How would I get it out of string form and calculate the answer? I tried using float(), int(float()) but I'm not sure if that's for numbers only or not.

2
  • You can either use eval as Avinash suggested or write your own parser Commented Oct 9, 2015 at 3:14
  • Unfortunately, the parser in that link is going to be really unintelligent. It knows nothing of parenthesis for example :-). I've done this a few times using an ast.NodeVisitor, but every time I do it, I lose the code. I should keep it around sometime -- Just for fun. Commented Oct 9, 2015 at 5:14

2 Answers 2

16

I've written this a couple times, and every time it seems that I lose the code...

A very simple (and "safe") calculator can be created using ast:

import ast
import operator

_OP_MAP = {
    ast.Add: operator.add,
    ast.Sub: operator.sub,
    ast.Mult: operator.mul,
    ast.Div: operator.div,
    ast.Invert: operator.neg,
}


class Calc(ast.NodeVisitor):

    def visit_BinOp(self, node):
        left = self.visit(node.left)
        right = self.visit(node.right)
        return _OP_MAP[type(node.op)](left, right)

    def visit_Num(self, node):
        return node.n

    def visit_Expr(self, node):
        return self.visit(node.value)

    @classmethod
    def evaluate(cls, expression):
        tree = ast.parse(expression)
        calc = cls()
        return calc.visit(tree.body[0])


print Calc.evaluate('1 + 3 * (2 + 7)')

This calculator supports numbers, addition, subtraction, division, multiplication and negation (e.g. -6) and parenthesised groups. Order of operations are the same as Python which should be relatively intuitive... It can (almost trivially) be extended to support just about any unary or binary operator that python supports by adding the ast node type and corresponding operator/function to the _OP_MAP above.

Sign up to request clarification or add additional context in comments.

4 Comments

This is the best python string calculator out there. There should be a link from all those others to here. I spent hours looking until I found this one.
I am working on a Linux accounting program called PyGtk Posting, licensed under GPLv3. Could I have your permission to include this code, and license it GPLv3? Otherwise, what license do you prefer?
@theGtknerd -- If this code is going to be licensed, I'd want it to be something nice and permissive (e.g. Apache 2.0, MIT, ...). I have no problem with you using it in your project as long as the GPL doesn't somehow magically start applying to this code as well preventing it's use in other (commercial) applications.
Apache 2.0 and GPLv3 are compatible. See my commit. Thanks.
10

You may use eval

>>> function = '(2*1)+3'
>>> eval(function)
5

As @mgilson said,

Only do this if you completely trust the source of the string.

2 Comments

Note, Only do this if you completely trust the source of the string :-)
function is a bad name for a string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.