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 种设计模式中的所有模式!🎉

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐