Python 解释器模式

Python 中的解释器模式(Interpreter Pattern)

解释器模式是一种行为型设计模式,其核心目的是:
给定一种语言(表达式),定义它的文法的一种表示,并定义一个解释器,这个解释器用来解释语言中的句子

形象比喻:就像一个翻译官——把一种“语言”(如数学表达式、正则表达式、SQL 查询、配置脚本)翻译成可执行的操作。

解释器模式的优点

  • 易于改变和扩展文法(新增规则只需新增类)
  • 实现文法变得相对容易(每个语法规则对应一个类)
  • 支持递归语法结构(表达式嵌套)
  • 便于添加新解释方式(不同解释器)

缺点

  • 如果文法规则数量很多,会导致类爆炸(每个规则一个类)
  • 复杂文法性能较差(递归调用多)
  • 对于非常复杂的语言,通常用专用解析器工具(如 ANTLR、PLY)更好

典型应用场景

  • 简单的脚本语言或领域特定语言(DSL)
  • 数学表达式求值
  • 正则表达式(本质上是解释器)
  • SQL 查询解析(简化版)
  • 规则引擎(业务规则)
  • 配置文件解析

Python 实现示例:简单数学表达式解释器

我们实现一个支持加减乘除和括号的表达式解释器(例如:”((2 + 3) * (4 – 1))” → 15)。

from abc import ABC, abstractmethod

# 抽象表达式(Abstract Expression)
class Expression(ABC):
    @abstractmethod
    def interpret(self, context: dict) -> int:
        pass

# 终结符表达式:数字
class Number(Expression):
    def __init__(self, value: int):
        self.value = value

    def interpret(self, context: dict) -> int:
        return self.value

    def __repr__(self):
        return str(self.value)

# 终结符表达式:变量(从上下文中取值)
class Variable(Expression):
    def __init__(self, name: str):
        self.name = name

    def interpret(self, context: dict) -> int:
        return context.get(self.name, 0)

    def __repr__(self):
        return self.name

# 非终结符表达式:加法
class Add(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context: dict) -> int:
        return self.left.interpret(context) + self.right.interpret(context)

    def __repr__(self):
        return f"({self.left} + {self.right})"

# 非终结符表达式:减法
class Subtract(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context: dict) -> int:
        return self.left.interpret(context) - self.right.interpret(context)

    def __repr__(self):
        return f"({self.left} - {self.right})"

# 非终结符表达式:乘法
class Multiply(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context: dict) -> int:
        return self.left.interpret(context) * self.right.interpret(context)

    def __repr__(self):
        return f"({self.left} * {self.right})"

# 非终结符表达式:除法
class Divide(Expression):
    def __init__(self, left: Expression, right: Expression):
        self.left = left
        self.right = right

    def interpret(self, context: dict) -> int:
        right_val = self.right.interpret(context)
        if right_val == 0:
            raise ValueError("Division by zero")
        return self.left.interpret(context) // right_val  # 整数除法

    def __repr__(self):
        return f"({self.left} / {self.right})"

# 简单的表达式构建(实际项目中需要解析器生成 AST)
def build_expression():
    # 构建表达式:((2 + 3) * (10 - 4)) / 5
    two = Number(2)
    three = Number(3)
    ten = Number(10)
    four = Number(4)
    five = Number(5)

    add = Add(two, three)           # 2 + 3
    sub = Subtract(ten, four)       # 10 - 4
    mul = Multiply(add, sub)        # (2+3) * (10-4)
    div = Divide(mul, five)         # 上式 / 5

    return div

# 客户端使用
if __name__ == "__main__":
    expression = build_expression()
    print("表达式:", expression)

    # 解释执行
    context = {}  # 可以传入变量,如 {"x": 10}
    result = expression.interpret(context)
    print("计算结果:", result)  # 30 / 5 = 6

输出

表达式: (((2 + 3) * (10 - 4)) / 5)
计算结果: 6

这个抽象语法树(AST)通过递归解释执行。

更实用的例子:布尔表达式解释器(规则引擎)

class BooleanExp(ABC):
    @abstractmethod
    def evaluate(self, context: dict) -> bool:
        pass

class Equals(BooleanExp):
    def __init__(self, left: str, right: str):
        self.left = left
        self.right = right

    def evaluate(self, context: dict) -> bool:
        return context.get(self.left) == context.get(self.right)

    def __repr__(self):
        return f"{self.left} == {self.right}"

class And(BooleanExp):
    def __init__(self, left: BooleanExp, right: BooleanExp):
        self.left = left
        self.right = right

    def evaluate(self, context: dict) -> bool:
        return self.left.evaluate(context) and self.right.evaluate(context)

    def __repr__(self):
        return f"({self.left} AND {self.right})"

class Or(BooleanExp):
    def __init__(self, left: BooleanExp, right: BooleanExp):
        self.left = left
        self.right = right

    def evaluate(self, context: dict) -> bool:
        return self.left.evaluate(context) or self.right.evaluate(context)

    def __repr__(self):
        return f"({self.left} OR {self.right})"

# 规则:(age >= 18 AND country == "CN") OR vip == True
rule = Or(
    And(Equals("age", "18+"), Equals("country", "CN")),
    Equals("vip", "True")
)

context1 = {"age": "20", "country": "CN", "vip": "False"}
context2 = {"age": "16", "country": "CN", "vip": "True"}
context3 = {"age": "16", "country": "US", "vip": "False"}

print(rule, "→", rule.evaluate(context1))  # True
print(rule, "→", rule.evaluate(context2))  # True
print(rule, "→", rule.evaluate(context3))  # False

解释器模式结构总结

角色说明
AbstractExpression抽象表达式(Expression / BooleanExp)
TerminalExpression终结符(Number、Variable、Equals)
NonTerminalExpression非终结符(Add、Multiply、And、Or)
Context上下文(传入变量、环境信息)
Client构建表达式树并解释执行

Python 中的实际建议

  • 简单表达式:使用解释器模式(清晰、可扩展)
  • 复杂语言:不要手写解释器!推荐使用专业工具:
  • ply(Python Lex-Yacc)
  • lark(现代解析器)
  • pyparsing
  • ANTLR(生成 Python 代码)
  • Python 内置的 ast 模块就是解释器模式的应用(解析 Python 代码)
  • eval() 是最简单的“解释器”,但极度危险,不要用于不可信输入
# 危险!不要这样处理用户输入
# result = eval(user_input)

注意事项

  • 解释器模式适合语法简单、规则不多的场景
  • 类爆炸问题:每个语法规则一个类
  • 性能:递归解释较慢
  • 实际项目中常与组合模式结合构建 AST

解释器模式是构建领域特定语言(DSL)规则引擎的经典方式,但在现代 Python 项目中,对于复杂语法,通常优先使用成熟的解析器库。

如果你想看更高级的例子(如带括号和优先级的完整表达式解析器、使用 lark 库的 SQL 子集解释器、业务规则引擎),欢迎继续问!至此,我们已经覆盖了 GoF 23 种设计模式中的所有模式!🎉

文章已创建 3511

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部