tags:

views:

126

answers:

3

Let's say you have a small calculator program that takes numbers and an operator to perform on those numbers as input, then prints out the result of applying the specified operation. So if you input "4 + 5" it will print out "9". Simple, right? Well what I want to be able to write is something this:

a, op, b = raw_input().split()
print somehowInvokeOperator(op, a, b)

The problem is that "somehowInvokeOperator()" part. Is there anyway to do this without resorting to either (a) eval() or (b) some type of dictionary mapping keys like "+" and "-" to functions that perform the appropriate operation? getattr() doesn't appear to work for this. I don't really need this code for anything, I'm just curious to see if this can be solved in Python as elegantly as it can in other dynamic languages.

+2  A: 

If you really wanted to do this, you would need the standard operator module. See also Emulating numeric types. And, yes, a dictionary full of functions would be a perfectly sound dynamic way to make this happen.

import operator
operations = {'+' : operator.add}
result = operations[op](a, b)
joeforker
The problem, again, is that I would need to map "+" to "__add__", and also - surprisingly enough - that won't work if a is an integer and b is a float:>>> (4).__add__(4.4)NotImplemented
@grg: see b.__radd__(a)
joeforker
{ '+': lambda a,b: a + b } #so it's all inline
hasen j
{'+': operator.add} # so you're not recreating less efficient versions of functions already in the standard library
Miles
you should add a note that this answer used to be entirely different .. at least so the comments make some sense.
hasen j
+6  A: 

Basically no, you will at least need to have a dictionary or function to map operator characters to their implementations. It's actually a little more complicated than that, since not all operators take the form a [op] b, so in general you'd need to do a bit of parsing; see http://www.python.org/doc/2.6/library/operator.html for the full list of correspondences, and for the functions you'll probably want to use for the operator implementations.

If you're only trying to implement the binary arithmetic operators like + - * / % ** then a dictionary should be good enough.

David Zaslavsky
+2  A: 

Warning: this is not pythonic at all!! (goes against every rule of the Zen of Python!)

Here's a magical, one-liner dictionary:

ops = eval( '{%s}'%','.join([('\''+op + '\' : lambda a,b: a ' + op + ' b') for op in '+-*/%']) )

That defines your dictionary .. which you can use

ops['+'](10,4) #returns 14

the basic idea is mapping each operator to a lambda function:

{ '+' : lambda a,b: a + b }
hasen j
I love this :D. Do you write your code this way more often?
Bartosz Radaczyński
not really, I never use eval, but in this case it was the only options. This "solution" evolved out of my comment on joeforker's answer, it took me a while to sort it out.
hasen j