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(现代解析器)pyparsingANTLR(生成 Python 代码)- Python 内置的
ast模块就是解释器模式的应用(解析 Python 代码) eval()是最简单的“解释器”,但极度危险,不要用于不可信输入
# 危险!不要这样处理用户输入
# result = eval(user_input)
注意事项
- 解释器模式适合语法简单、规则不多的场景
- 类爆炸问题:每个语法规则一个类
- 性能:递归解释较慢
- 实际项目中常与组合模式结合构建 AST
解释器模式是构建领域特定语言(DSL)和规则引擎的经典方式,但在现代 Python 项目中,对于复杂语法,通常优先使用成熟的解析器库。
如果你想看更高级的例子(如带括号和优先级的完整表达式解析器、使用 lark 库的 SQL 子集解释器、业务规则引擎),欢迎继续问!至此,我们已经覆盖了 GoF 23 种设计模式中的所有模式!🎉