You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何使用递归函数将表达式tokens转换为指定结构运算树

Python表达式Tokens转指定结构语法树实现方案

核心实现基于递归下降+优先级匹配思路,不需要引入第三方库,完全匹配要求的两种转换规则。

前置定义

首先明确运算符优先级,数字、括号做特殊处理:

# 优先级数值越小,运算优先级越低,在语法树中越靠近上层
OP_PRIORITY = {
    '+': 1,
    '-': 1,
    '*': 2,
    '/': 2
}

辅助函数:括号位置匹配

处理括号结构前,需要先定位每个左括号对应的右括号索引,避免误判括号内部的运算符:

def find_matching_bracket(tokens, start_idx):
    """start_idx 必须是左括号'('的索引,返回对应配对右括号的索引"""
    count = 0
    for i in range(start_idx, len(tokens)):
        if tokens[i] == '(':
            count += 1
        elif tokens[i] == ')':
            count -= 1
            if count == 0:
                return i
    raise ValueError("括号不匹配")

核心递归转换函数

递归逻辑遵循三个处理顺序:

  • 边界判定:当前处理段只有单个数字,直接包装为叶子节点[数字]
  • 括号识别:如果当前处理段是括号包裹的内容,先递归处理括号内部表达式,再套入要求的[[内部处理结果], "(", []]结构
  • 优先级拆分:遍历当前段,跳过所有括号内部的内容,找到优先级最低、位置最靠右的运算符作为当前层的根节点,将tokens拆分为运算符左右两段,分别递归处理后拼接为当前层结构
def tokens_to_tree(tokens):
    # 边界情况:单个数字,返回叶子节点
    if len(tokens) == 1:
        return [tokens[0]]
    
    # 先检查当前段是否被完整括号包裹
    if tokens[0] == '(':
        match_rb = find_matching_bracket(tokens, 0)
        if match_rb == len(tokens) - 1:
            # 整段被括号包裹,处理内部后套括号结构
            inner_tree = tokens_to_tree(tokens[1:-1])
            return [inner_tree, "(", []]
    
    # 寻找当前层的拆分运算符:优先级最低、不在括号内、最靠右的运算符
    split_idx = -1
    current_lowest_pri = float('inf')
    i = 0
    while i < len(tokens):
        if tokens[i] == '(':
            # 跳过整个括号段,不处理内部运算符
            i = find_matching_bracket(tokens, i) + 1
            continue
        if tokens[i] in OP_PRIORITY:
            op_pri = OP_PRIORITY[tokens[i]]
            # 同优先级选最靠右的,适配左结合运算规则
            if op_pri <= current_lowest_pri:
                current_lowest_pri = op_pri
                split_idx = i
        i += 1
    
    if split_idx == -1:
        raise ValueError(f"无效表达式段: {tokens}")
    
    # 拆分左右段递归处理
    left_part = tokens[:split_idx]
    op = tokens[split_idx]
    right_part = tokens[split_idx+1:]
    
    return [tokens_to_tree(left_part), op, tokens_to_tree(right_part)]

效果验证

直接跑给出的两个示例,输出完全匹配规则:

# 测试1:无括号的四则运算
test1 = ["12", "+", "2", "*", "3"]
print(tokens_to_tree(test1))
# 输出:[['12'], '+', [['2'], '*', ['3']]]

# 测试2:带括号的运算
test2 = ["(", "2", "+", "3", ")", "*", "7"]
print(tokens_to_tree(test2))
# 输出:[[[['2'], '+', ['3']], '(', []], '*', ['7']]

扩展说明

如果后续需要支持更高优先级的运算符(比如幂运算**、取模%),只需要在OP_PRIORITY字典里补充对应运算符和优先级数值即可,不需要修改核心递归逻辑。

内容的提问来源于stack exchange,提问作者gina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 05:15:42