【发布时间】:2021-10-10 14:13:01
【问题描述】:
我正在编写一种命令行用户界面,可以将任意布尔表达式作为输入。必须在某个更新后更改的字典上重复评估此表达式。
这是简化的代码:
import traceback
def update_my_dict():
return {'a': 1}
my_dict = {'a': 0}
bool_exp = input()
# -- verify code can be executed in the current context
try:
result = eval(bool_exp, my_dict)
except Exception:
print(f'Expression cannot be evaluated, evaluation raise the following error:')
print(traceback.format_exc())
quit()
# -- verify code return a boolean
if not isinstance(result, bool):
print(f'Expression return {type(result)}, expect bool')
quit()
# -- go
while not eval(bool_exp, my_dict):
my_dict = update_my_dict()
在运行最后一个 while 循环之前,我想验证表达式是否可以在当前上下文中执行,并确保它返回一个布尔值。
我的问题是,如果表达式是,例如 bool_exp = a == 1 and b == 2 表达式的第一个测试评估,同时返回 false 但不引发异常,因为关闭了惰性评估。但是当my_dict 更新时,就会报错。
那么,是否可以通过某种方式禁用第一次测试评估的惰性/短路评估?我使用ast 搜索了一些解决方案,但它似乎很复杂,因为bool_exp 可以是任意长且复杂的,例如包含纠缠的布尔表达式等。
PS:我知道eval() 在一般情况下是不安全的,但我的代码将无法在外部使用
PS2:我知道它可以在 while 循环中捕获异常,但它看起来有点优化,因为知道 my_dict 键在更新时永远不会改变,只会改变它们的值。此外,这个问题更像是是否可以控制评估行为
编辑
“但你可以使用 & 和 | 代替 and 和 or !”
不,我不知道将输入什么作为输入。所以用户可以输入任何他想要的。
正确的输入表达式:
- 应该返回一个布尔值。
- 在测试中应该只涉及字典键。
“正确”意味着它将在结束的 while 循环中重复评估,而不会引发任何异常。
我们假设字典中的键将保持不变。即只有字典的值会在更新阶段发生变化。换句话说,第一个try/except 旨在验证表达式仅对my_dict 中的变量进行一些测试。
我无法进一步解释它的全球使用情况,否则我需要很长的帖子,丢失看似无关的信息来解决问题。
【问题讨论】:
-
这能回答你的问题吗? Python: Avoid short circuit evaluation
-
请问您真正想用这段代码实现什么?
-
@Welgriv 但问题是布尔运算符对吗?正如链接问题的答案所建议的那样,您可以轻松地
replace与非短路对应物&和|? -
@L.Grozinger 二元运算符
&和|与逻辑运算符and和or的优先级不同。最重要的是,它们位于比较运算符==、<、...的对立面。 -
不,不会。您已经在每次更新时对其进行评估:
while not eval(bool_exp, my_dict):。唯一添加的操作是if not isinstance(result, bool):,我高度怀疑会以任何方式影响性能
标签: python