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.
-
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 : @grg: see b.__radd__(a)hasen j : { '+': lambda a,b: a + b } #so it's all inlineMiles : {'+': operator.add} # so you're not recreating less efficient versions of functions already in the standard libraryhasen j : you should add a note that this answer used to be entirely different .. at least so the comments make some sense. -
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.
-
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 }
Bartosz RadaczyĆski : I love this :D. Do you write your code this way more often?hasen j : 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.
0 comments:
Post a Comment