Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check conditions stored as strings? Do I need a parser?

I have some conditions/comparisons stored as strings. How can I check these conditions? A very simple example is given below. I want the conditions as strings because I want to print them in case they fail.

I think I'll need to make a parser for this but that would be a really stupid idea to make a complete Python parser for a small thing. Any ideas what can be done?

def rev_num(num):
    if num < 0:
        return -int(str(-num)[::-1])
    else:
        return int(str(num)[::-1])

conditions = ['rev_num(-34) != -43', 'rev_num(34) != 43']

for i in conditions:
     if something-needs-to-come-here(i):
           print(i)

I know this is a weird idea but please tag along if you can.


I caused some confusion to user2357112. He pointed out that what I am trying to do is called unit-testing. Thanks for that.

To avoid any further confusion I'll add the code that I am trying to improve. The change that I want to make is to print the condition in the function correctness which made it return False.

def rev_num(num):
    if num < 0:
        return -int(str(-num)[::-1])
    else:
        return int(str(num)[::-1])

if __name__ == "__main__":
    from timeit import Timer
    import random

    def correctness(f):
        print("Correctness Test")
        if f(-34) != -43 or f(34) != 43:
            return False
        print('Correct')
        print('-----------')
        return True

    def timing(f, times):
        def test1(f):
            f(random.randint(1, 1000))
        def test2(f):
            f(random.randint(100000, 1000000))

        print("Timing Test")
        print(Timer(lambda: test1(f)).timeit(number = times))
        print(Timer(lambda: test2(f)).timeit(number = times))
        print('-----------')

    def tests(f,times):
        print(f.__name__)
        print('-----------')
        if correctness(f) is True:
            timing(f, times)

    repeat = 100000
    tests(rev_num, repeat)
like image 954
Aseem Bansal Avatar asked Dec 05 '25 19:12

Aseem Bansal


2 Answers

You could use eval, but I wouldn't suggest to do so. If you already know that you want to perform several calls to rev_num(x) != y, just create an auxiliary function and use a list of tuples to store the arguments:

def check_condition(x, y):
    return rev_num(x) != y

conditions = [(-34, -43), (34, 43)]

for i in conditions:
    if check_condition(*i):
        print('rev_num({}) != {}'.format(*i))
like image 62
A. Rodas Avatar answered Dec 08 '25 09:12

A. Rodas


You can do that using eval(cond_string):

for i in conditions:
     if eval(i):
           print(i)

Edit: yes, as several have pointed out, eval can be dangerous if you can't be absolutely certain about the content of the strings you're evaluating. For that reason, using eval is often seen as bad general practice, even though it may be the simplest way to achieve what you're aiming for here.

If your purpose is to perform sanity checks for code maintenance purposes, you could also take a look at the unittest module.

like image 24
ali_m Avatar answered Dec 08 '25 07:12

ali_m



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!