在Python中动态评估简单的布尔逻辑
我有一些动态生成的布尔逻辑表达式,例如:
- (A 或 B) 和 (C 或 D)
- A 或 (A 和 B)
- A
- 空 - 计算结果为 True
占位符被替换为布尔值。我应该
- 将此信息转换为 Python 表达式,例如
True or (True or False)
和eval
吗? - 创建一个二叉树,其中节点是
bool
或Conjunction
/Disjunction
对象并递归地评估它? - 将其转换为嵌套的 S 表达式并使用 Lisp 解析器?
- 还有别的事吗?
欢迎提出建议。
I've got some dynamically-generated boolean logic expressions, like:
- (A or B) and (C or D)
- A or (A and B)
- A
- empty - evaluates to True
The placeholders get replaced with booleans. Should I,
- Convert this information to a Python expression like
True or (True or False)
andeval
it? - Create a binary tree where a node is either a
bool
orConjunction
/Disjunction
object and recursively evaluate it? - Convert it into nested S-expressions and use a Lisp parser?
- Something else?
Suggestions welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这是我用大约一个半小时构建的一个小模块(可能有 74 行,包括空格)(加上近一个小时的重构):
简单的测试给出:
[部分偏离主题可能]
注意,您可以轻松地配置您使用的标记(操作数和运算符)以及提供的穷人依赖注入方法(
token_to_char=token_to_char
和朋友)以具有多个同时使用不同的求值器(仅重置“默认注入”全局变量将使您保持单一行为)。例如:
给出:
Here's a small (possibly, 74 lines including whitespace) module I built in about an hour and a half (plus almost an hour to refactoring):
The simple tests give:
[Partially off-topic possibly]
Note, the you can easily configure the tokens (both operands and operators) you use with the poor-mans dependency-injection means provided (
token_to_char=token_to_char
and friends) to have multiple different evaluators at the same time (just resetting the "injected-by-default" globals will leave you with a single behavior).For example:
gives:
编写一个可以处理此问题的评估器应该不难,例如使用 pyparsing。您只需处理一些操作(与、或和分组?),因此您应该能够自己解析和评估它。
您不需要显式地形成二叉树来计算表达式。
It shouldn't be difficult at all to write a evaluator that can handle this, for example using pyparsing. You only have a few operations to handle (and, or, and grouping?), so you should be able to parse and evaluate it yourself.
You shouldn't need to explicitly form the binary tree to evaluate the expression.
如果您使用您关心的本地变量和全局变量设置字典,那么您应该能够安全地将它们与表达式一起传递到
eval()
。If you set up dicts with the locals and globals you care about then you should be able to safely pass them along with the expression into
eval()
.使用 SymPy 逻辑模块听起来像是小菜一碟。他们甚至在文档中提供了一个示例:http://docs.sympy。 org/0.7.1/modules/logic.html
Sounds like a piece of cake using SymPy logic module. They even have an example of that on the docs: http://docs.sympy.org/0.7.1/modules/logic.html
我写这篇文章是因为我今天解决了类似的问题,并且当我寻找线索时我就在这里。 (带有任意字符串标记的布尔解析器,稍后会转换为布尔值)。
在考虑了不同的选择(自己实现解决方案或使用某些包)后,我决定使用 Lark, https:// /github.com/lark-parser/lark
如果您使用 LALR(1),它会很容易使用并且速度相当快
这是一个可以匹配您的语法的示例
注意:我选择的正则表达式与空字符串不匹配故意的(Lark 由于某种原因不允许这样做)。
I am writing this because I had a solve a similar problem today and I was here when I was looking for clues. (Boolean parser with arbitrary string tokens that get converted to boolean values later).
After considering different options (implementing a solution myself or use some package), I settled on using Lark, https://github.com/lark-parser/lark
It's easy to use and pretty fast if you use LALR(1)
Here is an example that could match your syntax
Note: the regex I chose doesn't match the empty string on purpose (Lark for some reason doesn't allow it).
您可以使用 Lark 语法库https://github.com/lark-parser/lark
You can perform that with Lark grammar library https://github.com/lark-parser/lark
这可能是一个更简单的方法:
输出:
This might be a more easier approach to this:
Output: