'Is there a way to use eval() and a dictionary if input could be None?

I have some code with a lot of stacked if statements that I'm trying to make more pythonic. One of the segments of code boils down to three separate "values".

0.9 if 10<x>=20
0.75 if x>20
1 if x<10 or x is None

I tried sticking this in a dictionary to run through a function I made for a less complex (integers only) dictionary but am not sure how to handle None inputs.

def wallrat(val, table):
    try:
        # Create true/false list based on input value
        chks = [eval(v.replace('x',str(val))) for v in table.values()]
        # Find which value is true and verify that there's only one true value
        if True in chks and chks.count(True) == 1:
            # find the key that's true
            v = chks.index(True)
            table_list = list(table)
            # Loop through keys and values in dictionary
            return table_list[v]

age_dict = {0.9: '10< x >=20', 0.75: 'x > 20', 1:'x<10 or x is None'}

The above code obviously errors since if x == None, it can't do the other evaluations of 10< None >=20. I'm not sure how to pythonically handle this situation. Is it even possible to have a dictionary that tests both None and ints/floats? Or am I stuck having to use only x < 10 and use a separate segment of code to output the value of 1 if the input is None?

EDIT: I don't want to delete the question, but ended up just utilizing an If ... is not 'None' and an else statement to capture the 'None' = 1 assignment.

Comments and answers may provide helpful reconsideration to others utilizing eval(). In my specific use-case, there is no way for the input to contain malicious strings due to what the input data is (GIS feature class tables with integer fields or a coded int variable based on input date fields). Regardless though, I wasn't aware of the concerns about using eval() and the comments provide good information IMO.



Solution 1:[1]

You can use a list of lambdas that contain the logic you need instead of eval as it is a potential security risk and almost always not needed.

checks = [lambda x: .75 if x > 20 else ..., lambda x: 1 if x is None or x < 10 else ...]

Solution 2:[2]

If you want to achieve this if/else test in a single line, then using the python ternary syntax is probably the most readable option, and much safer & faster than eval with a dictionary of tests:

1 if x is None or x < 10 else 0.9 if 10 <= x <= 20 else 0.75

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mwo
Solution 2 match