为此构建一个解析器并不困难.您可以使用operator
包来处理条件,除此之外,它只是一堆格式化和循环数据.
import operator, re
# dictionary of operators
operators = {'<' :operator.lt,
'<=':operator.le,
'==':operator.eq,
'>=':operator.ge,
'>' :operator.gt,
'!=':operator.ne
}
# format operators keys for regex group
_oper = '|'.join(operators.keys())
# regex
oper = re.compile(fr'\s*({_oper})\s*').split
number = re.compile(r'-?\d*(\.\d+)?').fullmatch
string = re.compile(r'("|\')(?P<str>.*)\1').fullmatch
def cast(value:str) -> float|int|bool|str|None:
out = None
if (v := value.lower()) in ('true', 'false'):
out = v == "true"
elif m := string(value):
out = m.group('str')
elif m := number(value):
out = (int,float)['.' in v](v)
return out
def check_conditions(data:dict, conditions:str) -> bool:
# stores condition results
facts = []
for cond in conditions.split(','):
# stores values and operators
v, o = [], []
# parse values and operators
for c in oper(cond):
if (c := c.strip()) in operators:
# store operator function
o.append(operators.get(c))
else:
# try data[c] else cast c
v.append(data.get(c, cast(c)))
# make sure values length is one more than operators
if (len(v) - len(o)) != 1:
raise ValueError
# call all operator functions on values and store results
facts += [o[i](*v[i:i+2]) for i in range(len(o))]
return all(facts)
usage
data = {'a':25, 'ab':3.3, '(cd)': 4, 'ef':35, 'gh':.2, 'ij':"hello", 'kl':False, "mn":None}
conds = 'mn==None, a>5, 0<(cd)<5, 35==ef!=34>12<20, ij==\'hello\''
print(check_conditions(data, conds)) #True