75

I'd like to pass a math operator, along with the numeric values to compare, to a function. Here is my broken code:

def get_truth(inp,relate,cut):    
    if inp print(relate) cut:
        return True
    else:
        return False

and call it with

get_truth(1.0,'>',0.0)

which should return True.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
philshem
  • 24,761
  • 8
  • 61
  • 127

5 Answers5

103

Have a look at the operator module:

import operator
get_truth(1.0, operator.gt, 0.0)

...

def get_truth(inp, relate, cut):    
    return relate(inp, cut)
    # you don't actually need an if statement here
grc
  • 22,885
  • 5
  • 42
  • 63
58

Make a mapping of strings and operator functions. Also, you don't need if/else condition:

import operator


def get_truth(inp, relate, cut):
    ops = {'>': operator.gt,
           '<': operator.lt,
           '>=': operator.ge,
           '<=': operator.le,
           '==': operator.eq}
    return ops[relate](inp, cut)


print(get_truth(1.0, '>', 0.0)) # prints True
print(get_truth(1.0, '<', 0.0)) # prints False
print(get_truth(1.0, '>=', 0.0)) # prints True
print(get_truth(1.0, '<=', 0.0)) # prints False
print(get_truth(1.0, '==', 0.0)) # prints False

FYI, eval() is evil: Why is using 'eval' a bad practice?

Michael Dorner
  • 17,587
  • 13
  • 87
  • 117
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
13

Use the operator module. It contains all the standard operators that you can use in python. Then use the operator as a functions:

import operator

def get_truth(inp, op, cut):
    return op(inp, cut):

get_truth(1.0, operator.gt, 0.0)

If you really want to use strings as operators, then create a dictionary mapping from string to operator function as @alecxe suggested.

Viktor Kerkez
  • 45,070
  • 12
  • 104
  • 85
1

Use the operator module instead:

import operator
def get_truth(inp, relate, cut):
    rel_ops = {
        '>': operator.gt,
        '<': operator.lt,
        '>=': operator.ge,
        '<=': operator.le,
        '==': operator.eq,
        '!=': operator.ne
    }
    return rel_ops[relate](inp, cut)
E_net4
  • 27,810
  • 13
  • 101
  • 139
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
-4
>>> def get_truth(inp,relate,cut):
...     if eval("%s%s%s" % (inp,relate,cut)):
...         return True
...     else:
...         return False
...
>>> get_truth(1.0,'>',0.0)
True
>>>
amadain
  • 2,724
  • 4
  • 37
  • 58
  • 11
    No, please don't use `eval()` when better solutions are available. – Martijn Pieters Sep 03 '13 at 12:11
  • what is your problem with eval??? You are downvoting everybody who has given a working solution that uses eval – amadain Sep 03 '13 at 12:13
  • 8
    `eval()` poses a security risk, and is way overused as a 'solution' whenever people do not know a better option exists. – Martijn Pieters Sep 03 '13 at 12:15
  • **[Do not ever use `eval` (or `exec`) on data that could possibly come from outside the program in any form. It is a critical security risk. You allow the author of the data to run arbitrary code on your computer](https://stackoverflow.com/questions/1832940/why-is-using-eval-a-bad-practice). It [cannot easily be sandboxed, and proper sandboxing is harder than using a proper tool for the job.](https://stackoverflow.com/questions/3068139)** – Karl Knechtel Mar 29 '23 at 01:09