python-3.x - 评估表达式时语法无效

标签 python-3.x syntax-error

我越来越

SyntaxError: invalid syntax





SyntaxError: invalid token



在字典中评估 bool 表达式时:

测试用例
test_expressions = ['(3530A338A58 OR 3533A500H65 OR 3533-555A57 OR 3533A593A36 OR 3533A637A60 OR 3533A636A67 OR 3533A637D30 OR 3533H370A53 OR  3533H370T63 OR 3533H693H95 OR 3533H693T57 OR 3533H873H98) AND NOT (3630H693H66 OR 3630D387A39)', 'NOT (TP(0330-000098) OR TP(0330H750A85))']

test_dict = dict((k, opt_exp_dict_clean[k]) for k in test_expressions if k in opt_exp_dict_clean)

print(test_dict)

{'(3530A338A58 OR 3533A500H65 OR 3533-555A57 OR 3533A593A36 OR 3533A637A60 OR 3533A636A67 OR 3533A637D30 OR 3533H370A53 OR  3533H370T63 OR 3533H693H95 OR 3533H693T57 OR 3533H873H98) AND NOT (3630H693H66 OR 3630D387A39)': '535A8300-503',
 'NOT (TP(0330-000098) OR TP(0330H750A85))': '336A5305-3'}

#Boolean-Normalize
opt_disp_dict_norm = {k: (True if v == "Accepted" else False) for k, v in opt_disp_dict_clean.items()}

#Replace Boolean Expressions
for expression, value in test_dict.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not")
    #Return Values From True Expressions
    if eval(expression, opt_disp_dict_norm):
        print(value)

哪个返回
  File "<string>", line 1
    (3530A338A58 or 3533A500H65 or 3533-555A57 or 3533A593A36 or 3533A637A60 or 3533A636A67 or 3533A637D30 or 3533H370A53 or  3533H370T63 or 3533H693H95 or 3533H693T57 or 3533H873H98) and not (3630H693H66 or 3630D387A39)
               ^

SyntaxError: invalid syntax




'NOT (TP(0330-000098) OR TP(0330H750A85))'返回:
  File "<string>", line 1
    not (TP(0330-000098) or TP(0330H750A85))
               ^

SyntaxError: invalid token



我认为这是我的术语格式的问题,因为这种方法适用于一般情况(如下)。我怎样才能使这些术语对python“评估友好”?

这些术语称为字母数字和() 的“选项”。和 -是唯一的特殊字符。

通用案例:
dict1 = {'((A OR D OR E) AND F) AND NOT G': 'Pickles', '(A AND B) OR E': 'Tuna', '(NOT G) AND (A OR B OR C OR D OR E)': 'Salami'}
dict2 = {'A': 'Accepted', 'B': 'Rejected', 'C': 'Rejected', 'D': 'Accepted', 'E': 'Rejected', 'F': 'Accepted', 'G': 'Rejected', 'Z': 'Accepted'}

#Boolean-Normalize

dict2_norm = {k: (True if v == "Accepted" else False) for k, v in dict2.items()}


#Replace Boolean Expressions   
for expression, value in dict1.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or")\    
    .replace("AND", "and").replace("NOT", "not") 
    #Return Values From True Expressions   
    if eval(expression, dict2_norm):    
        print(value)

返回
Pickles
Salami

编辑 1
opt_exp_dict_clean非常大,并且来自 csv 文件。这是 opt_exp_dict_clean 的示例:
opt_exp_dict_clean = { '(TP(2530-000580) OR TP(2530-000583) OR TP(2530-000582) OR 2530A627A05 OR 2530T652A06 OR 2530A250A38 OR 2530H633G23 OR 2530A560E37 OR 2530H636T83 OR 2530H632M38 OR 2530H636F05 OR 2530T333D72 OR 2530T723H37 OR 2530T920F60 OR 2530T983H28 OR 9800H396A37 OR 9800H396A69 OR 9800H502T33 OR 2530H632H82 OR 2530A688D82 OR 2530-003276 OR 2530-002999 OR 2530H363A37 OR 9800H502D03 OR 2530A079H59 OR 2530H335A07 OR 2530H833T37 OR 2530H635G33 OR 2530A093G52 OR 2530H632G50 OR 2530T323E83 OR 2530H508D56 OR 2530H633D08 OR 2530T323E83 OR 2530T537T29 OR 2530T333H39 OR 2530T537D03 OR 2530T323L09 OR 2530T323X30 OR 2530T593T37 OR 2530H673A30 OR 2530H637W80 OR 2530T537N65 OR 2530T537T96 OR 9800H502G93 OR 2530T806G76 OR 2530T333U72 OR 2530T882F90 OR 2530T893F63 OR 2530T920P90 OR 2530T882H68 OR 2530T920J93 OR 2530T806T99 OR 2530T806J33 OR 2530T882N32 OR 2530T537N35 OR 2530T995L50 OR 2530D305H26 OR 2530D305A80 OR 2530D360A85 OR 2530D305F33 OR 2530D362G73 OR 2530D383A32 OR 2530D360M37 OR 2530D360N26 OR 2530D603D39 OR 2530E339H37 OR 2530D6': '333A5720-85',
 'TP(0330-000099) AND NOT (2350-000233 OR 2350-000320 OR 2350A058H33 OR 3930-000322 OR 3630H693H66 OR 3630D387A39 OR 2350H693D00 OR 2350H693A33 OR TP(0330H750A85))': '232A3222-7',
 '(0330-000022 OR 0330-000029) AND NOT ((2323H299A26 AND 3363A333A30) OR 2323H372T80 OR 3930A398A60 OR 9800H396A67 OR 9800H396A86 OR 9800H396A88 OR 9800H396A89 OR 9800H396H25 OR 9800H332A26 OR 9800H332A29 OR 9800H760A20 OR 9800T858T69)': '233A3303-20',
 'TP(0330-000099) AND NOT (2533-000333 OR 2533A793H53 OR 3630H693H66 OR 3630D337A56 OR 3630D387A39 OR TP(0330H750A85))': '232A3203-2',
 '2500T803A90 AND (TP(2523-003280) OR TP(2523-003283) OR TP(2523H873A02) OR TP(2523A396H98) OR TP(2523H639A33) OR 2523T882M53 OR 2523T995J72 OR 2523D350A03 OR 2523D072E33 OR 2523D305F86) AND (2370T869A37 OR 2375T869H29 OR 2370T869A33) AND (TP(3520T372A20) OR 3520T390A32 OR 3520-000253 OR 3520D033U92) AND NOT 3520T383T88': '333A2203-333H',
 '3833-000037 AND NOT TP(0330-000098)': '337A2530-8',
 '2530-002997 OR 2530A033S00 OR 2530A053I63 OR 2530A079H63 OR 2530A093G53 OR 2530A300L37 OR 2530A289T07 OR 2530A560E38 OR 2530A560L23 OR 2530A627A03 OR 2530A688G60 OR 2530A963A32 OR 2530H373A06 OR 2530H363A36 OR 2530H637D68 OR 2530H633G33 OR 2530H633P85 OR 2530H633Z78 OR 2530H636D33 OR 2530T323L37 OR 2530T333L03 OR 2530T537F78 OR 2530T537N36 OR 2530T537T99 OR 2530T537Y00 OR 2530T652A03 OR 2530T920W00 OR 2530T920G83 OR 2530D362G09': '337A5700-28'}
opt_disp_dict_clean 的样本:
opt_disp_dict_clean = {'2530T882N32': 'Accepted', 'TP(0330-000098)': 'Rejected', '2530A627A03': 'Accepted', '2530H633G33': 'Accepted', '2530A300L37': 'Rejected', '2523D072E33': 'Rejected', '3930-000322': 'Accepted', 'TP(0330-000099)': 'Rejected'}

在示例中,test_dict只是 opt_exp_dict_clean 的子集

没有 test_dict bool 电梯将显示:
#Boolean-Normalize
opt_disp_dict_norm = {k: (True if v == "Accepted" else False) for k, v in opt_disp_dict_clean.items()}

#Replace Boolean Expressions
for expression, value in opt_exp_dict_clean.items():
    expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not")
    #Return Values From True Expressions
    if eval(expression, opt_disp_dict_norm):
        print(value)

最佳答案

显然,问题在于 ID 都不像 2530T882N32也不是 TP(0330-000098)是有效的 Python 变量名,因此在尝试使用这些变量评估表达式时会产生语法错误。您可以更换/移除非法部件,例如以 _ 开头使它们成为合法的变量名称,但这可能会带来名称冲突的风险,并且可能难以将它们与原始对应项联系起来。

相反,我建议您将所有这些标识符包装到 d['...']使它们成为用于在字典中查找的字符串。然后将带有值的字典包装到另一个相应命名的字典中,然后再将其传递给 eval功能。在替换运算符后执行此操作,并且只匹配大写字母,这样运算符(然后是小写)也不会被换行。

您可以使用 re.sub 带有用于替换的回调函数。作为正则表达式,您可以使用例如TP\([^)]+\)|[-A-Z0-9]+ .请注意 TP部分必须先出现。

expression = expression.replace("XOR", "is not").replace("OR", "or").replace("AND", "and").replace("NOT", "not") 
expression = re.sub(r"TP\([^)]+\)|[-A-Z0-9]+", lambda m: "d['%s']" % m.group(), expression)
if eval(expression, {"d": opt_disp_dict_norm}):
    print(value)

但是请注意,我仍然收到一些 ID 的关键错误,并且第一个表达式缺少结束 ) .要处理丢失的 key ,您也可以替换为 "d.get('%s', True)""d.get('%s', False)"给那些default values .

关于python-3.x - 评估表达式时语法无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44185875/

相关文章:

c - 在配置阶段确定错误位置的工具/技巧 - PHP 扩展编码

python - 在 Python 中使用元组更新 2D 列表

python - ElementTree 返回元素而不是 ElementTree

python - 模块未找到错误: No module named 'tasklets'

ruby - 为什么使用 return 语句的带有双符号的 Ruby 表达式会导致语法错误

multidimensional-array - 尝试遍历Eiffel中的数组时出错

python - 自定义 Python 包 - django-paypal

python - 如何列出python3中脚本使用的所有python包

python - matplotlib : How to display graphs or figures with pylab

stored-procedures - 使用IF和THEN在Oracle 11g pl/sql中创建存储过程