如果您愿意进行改造,则无需编写自己的解析器S到适合使用的字符串eval() http://docs.python.org/2.7/library/functions.html#eval。改变S from '(A or B) and not(A and C)'
转化为等价的T使用Python的in-操作员'(x in A or x in B) and not(x in A and x in C)'
.
通过循环元素域并测试它们是否与上面的表达式匹配来计算结果。
这是交互式提示下的一个已解决的示例:
>>> T = '(x in A or x in B) and not(x in A and x in C)'
>>> sets = {'A': {0, 1}, 'B': {0, 2}, 'C': {1, 3}}
>>> universe = {x for s in sets.values() for x in s}
>>> {x for x in universe if eval(T, sets, {'x': x})}
set([0, 2])
要自动进行转换,请为集合变量创建一个命名空间,其中变量查找执行集合成员资格测试。将它们放在一起为您提供了一个简单而干净的集合表达式求值器:
class SetVariables(dict):
'Transform a variable lookup into a membership test'
def __getitem__(self, var):
s = dict.__getitem__(self, var)
return self.x in s
def set_eval(expr, **sets):
'Evaluation a set expression for the given sets'
universe = {x for s in sets.values() for x in s}
expr = compile(expr, '', 'eval')
variables = SetVariables(sets)
results = set()
for x in universe:
variables.x = x
if eval(expr, {}, variables):
results.add(x)
return results
if __name__ == '__main__':
print set_eval(expr = '(A or B) and not(A and C)',
A = {0, 1},
B = {0, 2},
C = {1, 3}
)
希望这能解决您的问题并使您不必编写自己的解析器:-)