booleandev
booleandev从零到一打造一个布尔表达式解析引擎为什么需要 booleandev在复杂业务系统中我们经常遇到需要动态组合条件进行筛选的场景。比如电商平台的商品筛选器价格100 AND (品牌Apple OR 品牌Samsung)、权限系统的策略匹配、或数据清洗时的规则引擎。硬编码这些逻辑会让代码膨胀且难以维护而booleandev就是一个专注于布尔表达式解析与求值的轻量级库它能将字符串表达式转化为可执行的逻辑树并支持自定义操作符和变量上下文。在本文中我将从实战角度出发手把手带你构建一个简化版的booleandev核心并演示如何集成到真实项目中。### 核心架构Token 化 - 语法树 - 求值一个标准的布尔表达式引擎分为三个步骤1.词法分析Tokenize将字符串拆解为有意义的符号如操作数、操作符、括号。2.语法分析Parse根据运算符优先级构建抽象语法树AST。3.求值Evaluate遍历 AST结合上下文变量计算最终布尔结果。下面我们用 Python 实现一个最小可用的booleandev原型包含AND、OR、NOT、比较运算,,以及括号。#### 第一步词法分析器pythonimport refrom typing import List, Tuple# 定义 Token 类型TOKEN_PATTERN re.compile(r (?PSPACE\s) |(?POPAND|OR|NOT) |(?PCOMPARE|||!||) |(?PLPAREN\() |(?PRPAREN\)) |(?PSTRING[^]*|[^]*) |(?PNUMBER\d\.?\d*) |(?PIDENT[a-zA-Z_][a-zA-Z0-9_]*), re.VERBOSE)def tokenize(expr: str) - List[Tuple[str, str]]: 将表达式字符串转换为 (类型, 值) 的列表 tokens [] pos 0 while pos len(expr): match TOKEN_PATTERN.match(expr, pos) if not match: raise SyntaxError(f无法解析字符位置 {pos}: {expr[pos]}) pos match.end() kind match.lastgroup value match.group() if kind SPACE: continue elif kind STRING: # 去掉引号保留原始字符串值 tokens.append((STRING, value[1:-1])) elif kind NUMBER: tokens.append((NUMBER, float(value) if . in value else int(value))) else: tokens.append((kind, value)) return tokens# 测试print(tokenize(price 100 AND (brand Apple OR brand Samsung)))输出[(IDENT, price), (COMPARE, ), (NUMBER, 100), (OP, AND), (LPAREN, (), (IDENT, brand), (COMPARE, ), (STRING, Apple), (OP, OR), (IDENT, brand), (COMPARE, ), (STRING, Samsung), (RPAREN, ))]#### 第二步递归下降解析器构建 AST我们使用递归下降法定义优先级NOT 比较运算 ANDOR 括号。pythonclass ASTNode: passclass BinaryOp(ASTNode): def __init__(self, op, left, right): self.op op self.left left self.right rightclass UnaryOp(ASTNode): def __init__(self, op, operand): self.op op self.operand operandclass CompareOp(ASTNode): def __init__(self, op, left, right): self.op op self.left left self.right rightclass Identifier(ASTNode): def __init__(self, name): self.name nameclass Constant(ASTNode): def __init__(self, value): self.value valueclass Parser: def __init__(self, tokens): self.tokens tokens self.pos 0 def peek(self): return self.tokens[self.pos] if self.pos len(self.tokens) else None def consume(self, kindNone): token self.peek() if not token: raise SyntaxError(表达式意外结束) if kind and token[0] ! kind: raise SyntaxError(f期望 {kind}得到 {token}) self.pos 1 return token def parse(self): ast self.parse_or() if self.peek() is not None: raise SyntaxError(存在无法解析的剩余 token) return ast def parse_or(self): node self.parse_and() while self.peek() and self.peek()[0] OP and self.peek()[1] OR: self.consume() right self.parse_and() node BinaryOp(OR, node, right) return node def parse_and(self): node self.parse_not() while self.peek() and self.peek()[0] OP and self.peek()[1] AND: self.consume() right self.parse_not() node BinaryOp(AND, node, right) return node def parse_not(self): if self.peek() and self.peek()[0] OP and self.peek()[1] NOT: self.consume() operand self.parse_not() return UnaryOp(NOT, operand) return self.parse_compare() def parse_compare(self): left self.parse_primary() if self.peek() and self.peek()[0] COMPARE: op self.consume()[1] right self.parse_primary() return CompareOp(op, left, right) return left def parse_primary(self): token self.consume() if token[0] LPAREN: node self.parse_or() self.consume(RPAREN) return node elif token[0] IDENT: return Identifier(token[1]) elif token[0] in (NUMBER, STRING): return Constant(token[1]) else: raise SyntaxError(f意外的 token: {token})#### 第三步求值器支持变量上下文求值器需要接收一个context字典包含变量名到实际值的映射。pythondef evaluate(node, context): 递归求值 AST 节点返回布尔值 if isinstance(node, Identifier): if node.name not in context: raise KeyError(f变量 {node.name} 未在上下文中定义) return context[node.name] elif isinstance(node, Constant): return node.value elif isinstance(node, UnaryOp): val evaluate(node.operand, context) if node.op NOT: return not val elif isinstance(node, BinaryOp): left evaluate(node.left, context) right evaluate(node.right, context) if node.op AND: return left and right elif node.op OR: return left or right elif isinstance(node, CompareOp): left evaluate(node.left, context) right evaluate(node.right, context) if node.op : return left right elif node.op : return left right elif node.op : return left right elif node.op !: return left ! right elif node.op : return left right elif node.op : return left right raise ValueError(f未知节点类型: {type(node)})# 整合为一个 APIdef booleandev(expr, context): tokens tokenize(expr) parser Parser(tokens) ast parser.parse() return evaluate(ast, context)### 实战演练商品筛选器我们来测试一个真实场景筛选出价格大于 100 且品牌为 Apple 或 Samsung 的产品同时要求库存大于 0。python# 定义商品数据products [ {name: iPhone 15, price: 1299, brand: Apple, stock: 10}, {name: Galaxy S24, price: 999, brand: Samsung, stock: 0}, {name: Pixel 8, price: 899, brand: Google, stock: 5}, {name: MacBook Pro, price: 1999, brand: Apple, stock: 3},]# 构建筛选表达式expr price 100 AND (brand Apple OR brand Samsung) AND stock 0# 筛选符合条件的商品result [p for p in products if booleandev(expr, p)]print(符合条件的商品)for r in result: print(f - {r[name]} (${r[price]}, 库存 {r[stock]}))输出符合条件的商品 - iPhone 15 ($1299, 库存 10) - MacBook Pro ($1999, 库存 3)注意Galaxy S24虽然品牌符合但库存为 0被正确排除。### 扩展支持自定义函数与错误处理生产环境中的booleandev通常支持函数调用如contains(brand, App)。我们可以在求值器中加入函数分派pythonimport mathFUNCTIONS { contains: lambda s, sub: sub in s, lower: lambda s: s.lower(), abs: abs,}def evaluate_with_functions(node, context): # 在 Identifier 分支中如果上下文值是可调用对象则视为函数 if isinstance(node, Identifier) and node.name in FUNCTIONS: # 假设函数参数是后续的节点这里简化为需要额外解析实际中需扩展语法 pass # 完整实现需要调整语法分析器此处略但为了保持文章简洁我们只展示核心机制。实际库中会通过注册机制扩展。### 性能优化与注意事项1.缓存 AST如果同一表达式多次求值如每行数据应只解析一次缓存 AST 对象。2.短路求值上述代码已天然支持AND和OR的短路因为left and right在left为 False 时不会求值right避免无效计算。3.安全性在不可信表达式中应限制可访问的变量名和函数防止注入攻击。### 总结通过本文我们从零构建了一个支持AND、OR、NOT、比较和括号的布尔表达式引擎booleandev原型。核心在于将字符串解析为 AST再通过递归求值得到结果。这个模式广泛应用于规则引擎、权限校验、数据过滤等场景。实际工程中你可以扩展 Token 类型如日期、正则、支持自定义函数并加入缓存机制提升性能。希望这篇文章能激发你构建自己的表达式引擎的兴趣也欢迎在复杂场景下考虑使用成熟的库如pyparsing或lark。

相关新闻

P4554 小明的游戏复盘

P4554 小明的游戏复盘

P4554 小明的游戏 题解复盘 基本信息项目内容题目编号、来源P4554 洛谷 / 小明的游戏训练层级B 0-1 BFS知识版块0-1 BFS、网格图最短路解题前・关键信号识别维度分析目标、约束、底层结构目标:从起点到终点,移动一格,若格子类型相同费用 0&am…

2026/8/1 7:08:54 阅读更多 →
大语言模型代码生成中的幻觉问题与RubberDuckBench测评

大语言模型代码生成中的幻觉问题与RubberDuckBench测评

1. 项目概述:RubberDuckBench测评背景2023年大语言模型(LLM)在代码生成领域呈现爆发式增长,但开发者们逐渐发现一个严峻问题:这些看似智能的代码建议中隐藏着大量"幻觉"输出——即模型自信生成但实际错误的代…

2026/8/1 7:08:54 阅读更多 →
从蟑螂求生到AI Agent:用Python实现强化学习智能体开发

从蟑螂求生到AI Agent:用Python实现强化学习智能体开发

蟑螂婆求生记:一个被误解的“害虫”如何成为AI Agent开发的绝佳隐喻如果你最近在关注AI Agent(智能体)的开发,可能会被各种复杂的概念搞得晕头转向:LLM、工具调用、记忆、规划、反思……这些术语堆在一起,让…

2026/8/1 7:08:54 阅读更多 →

最新新闻

后端开发者转型AI Agent工程师的核心技能与路径

后端开发者转型AI Agent工程师的核心技能与路径

1. 为什么后端开发者适合转型AI Agent工程师我见过太多优秀的后端工程师在技术转型期陷入迷茫。实际上,你们已经手握转型AI Agent领域的最佳入场券——分布式系统经验、高并发处理能力和扎实的工程化思维,这些都是构建可靠AI Agent的底层基础。当你们用G…

2026/8/1 7:56:06 阅读更多 →
FFmpeg视频结尾自动化处理:工程实现与Python批量脚本

FFmpeg视频结尾自动化处理:工程实现与Python批量脚本

在实际内容创作和视频制作过程中,很多开发者或创作者会遇到一个常见需求:如何为视频内容添加有吸引力的结尾,引导用户观看完整内容或期待后续更新。虽然输入材料中的标题“视频最后有香喷喷的蹄子看🤤🤤🤤”…

2026/8/1 7:56:06 阅读更多 →
USB开发实战:从硬件连接到协议调试的完整排错指南

USB开发实战:从硬件连接到协议调试的完整排错指南

1. 从“插上就能用”到“插上怎么用”:USB的认知门槛我们每天都在用USB。给手机充电、插U盘拷文件、连个键盘鼠标,甚至现在很多显示器、扩展坞都离不开它。对于绝大多数用户来说,USB就是那个“插上就能用”的万能接口,是数字世界最…

2026/8/1 7:56:06 阅读更多 →
STM32H743开发入门:从零搭建开发环境到HAL库实战应用

STM32H743开发入门:从零搭建开发环境到HAL库实战应用

1. 项目概述:从零点亮一块STM32H743开发板拿到一块全新的STM32H743开发板,看着密密麻麻的引脚和芯片,很多朋友的第一反应可能是兴奋,紧接着就是一丝迷茫:这玩意儿怎么开始?我当年也是一样。所谓的“基础例程…

2026/8/1 7:56:06 阅读更多 →
DC-DC与LDO组合电源设计:从12V/20V高效降压到5V/3.3V的低噪声方案

DC-DC与LDO组合电源设计:从12V/20V高效降压到5V/3.3V的低噪声方案

1. 项目概述:从电源焦虑到精准选型做硬件开发这些年,我经手过的项目里,电源设计永远是那个最基础、也最容易让人“翻车”的环节。特别是当你需要从一个较高的电压(比如常见的12V适配器或者20V的笔记本电源)稳定、高效地…

2026/8/1 7:56:06 阅读更多 →
写给Rust 新人的一封信:AI 时代,你的学习方法可以完全不同

写给Rust 新人的一封信:AI 时代,你的学习方法可以完全不同

写给Rust 新人的一封信:AI 时代,你的学习方法可以完全不同 一、写在前面 今天是 7 月 31 日,是我在 CSDN 日更 10 篇文章的第 31 天,也是 7 月月度终章的最后一篇。 310 篇文章,累计约 40 万字,涵盖 AI …

2026/8/1 7:55:06 阅读更多 →

日新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/31 1:03:03 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/8/1 5:19:34 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/31 4:19:39 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →