You should use lambdas or functions for this type of process. To do so, you would need to ensure that the variables used in the lambdas or functions are in scope of the declaration of your rules dictionary. But perhaps this may prove difficult if your code and rule declarations are not contained within a single function.
You have not posted enough contextual information/code for us to determine where your approach is failing, but perhaps an example will put you on the right track:
prices={
"set1": {
"price1": 200,
"price2": 300
},
"set2": {
"price1": 200,
"price2": 250
}
}
def Rule(expression,priceValue):
return (compile(expression,"<string>","eval"),priceValue)
rules={
"set1": [
Rule("a>0 and b<10 and price1>300",1.5),
Rule("a+b==10 or c>20",2.5)
],
"set2": [
Rule("a==c and b!=d or price2<100",3.5),
Rule("a==b and price2 in range(100,300)",4)
]
}
context = { "a":5, "b":5, "c":5, "d":0 }
for setId,priceSet in prices.items():
price = []
for rule,value in rules[setId]:
context.update(priceSet)
if eval(rule,globals(),context):
price.append(value)
print(setId,price,sum(price))
# set1 [2.5] 2.5
# set2 [3.5, 4] 7.5
- To make repeated eval() function calls faster, you can use compile()
to obtain a "compiled" version of your string formula. This is what
you should store in your rules dictionary.
- The content of a rule set only needs to be an array of tuples. This
will make using the rules list a bit easier.
- In your sample rule expressions, you are using a single equal sign
(=) for testing equality, Python needs a double equal sign otherwise
the formulas will not produce the expected results.
I am not sure what you meant by "it will add to prices in prices". Since your rules are already using price1 and price2 in their expressions, they seem to need the content of the prices dictionary (or at least one of its sets) to produce an answer. Why (and how) then would they update the very data structure that they rely upon to respond ? and with what keys ?. I could not produce an example that meets that requirement. Hopefully you will be able to adapt my example to your needs.