tags:

views:

124

answers:

7

How transform str('+') to mathematical operation? For example:

a = [0,1,2] # or a = ['0','1','2']
b = ['+','-','*']
c = int(a[0]+b[0]+a[1])

In other words, how transform str('-1*2') to int(), without for i in c: if i == '+': ... Thanks.

+2  A: 

i thin you're looking for eval(), but i advice to use something else... however,

>>> eval('-1*2')
-2

eval 'executes' the string you pass to it, like code. so it's quite dangerous for security, especially if the parameters are user input...

in this case i suggest to use parsing library, such as ply http://www.dabeaz.com/ply/ that for such thing is really simple to use and very effective :)

Ant
using a full implementation of lex/yacc is almost certainly overkill for this.
aaronasterling
maybe...but if he has to face this problem several time in his code, maybe with just a little bit more of operations, it's better to create a simple module or a class and pass the code to it...or he can implement his own parser ;) ( i really hate eval )
Ant
I too strongly distrust eval but a parser isn't necessary in this case: a filter on the allowed characters suffices. That also has the advantage of being less error prone and hence more secure. Also a module and classes are probably overkill as well - a simple function should work fine.
aaronasterling
uhm...yeah, maybe in this case too much OOP ;)
Ant
A: 

Use eval:

> eval(str('-1*2'))
> -2
StompChicken
A: 

Dett,

A Simple eval on the whole string... However be aware that if the user inputs the string, eval is risky, unless you do some parsing first

x = '-1*2'
y = eval(x)

y will then be the integer value.

Mark Ellul
+1  A: 

Use eval like everyone else is saying but filter it first.

>>> s = '1 + 12 / 2 - 12*31'
>>> allowed = set(' 1234567890()+-/*\\')
>>> if allowed.issuperset(s):
...     eval(s)
... 
-365
aaronasterling
+1. It's probably worth noting that even this isn't totally safe: for example, what happens if the input is `'99 ** 99 ** 99 ** 99 ** 99 ** 99 ** 99'`? But I don't see any vulnerabilities with this approach that could be avoided by parsing the input; either way I think you'd have to have CPU/memory usage limits in place. Unless you actually analyzed the parsed formula for various edge cases.
intuited
+1  A: 

You can read about http://en.wikipedia.org/wiki/Reverse_Polish_notation

DimaKrasun
+4  A: 

You can also use the operator module:

import operator as op
#Create a mapping between the string and the operator:
ops = {'+': op.add, '-': op.sub, '*': op.mul}

a = [0,1,2]
b = ['+','-','*']

#use the mapping
c = ops[b[0]](a[0], a[1])
Sacha
http://docs.python.org/library/operator.html#mapping-operators-to-functions
Sacha
+2  A: 

If your math expressions will fit Python syntax but you are skeered of eval (you should be) you can look into python's ast module (docs). It will parse the expression into an abstract syntax tree you can iterate over. You can evaluate a limited subset of Python and throw errors if you encounter anything outside your expression grammar.

Bill Gribble
Using the `ast` module is a good idea and you don't even have to parse the expression if you use the `ast.literal_eval()` [helper function](http://docs.python.org/library/ast.html#ast-helpers). From the docs: "This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself." Of course, this your input must be a string containing a valid Python expression.
martineau