三、Virtual Machine Software Architecture Style(虚拟机风格)
1、解释器风格
解释器风格是一种软件体系结构,它将输入的代码逐条解析并执行,无需事先编译。这种风格的特点是灵活、易于调试,但执行效率通常比编译型语言低。
解释器示例:解析并计算简单的算术表达式
#解析并计算简单的算术表达式
"""
接收用户输入的算术表达式:通过 input() 函数获取用户输入的表达式字符串。
词法分析:将输入的字符串分割成一个个有意义的符号(token),比如数字、运算符等。
语法分析:根据语法规则,判断输入的表达式是否合法,并构建抽象语法树(AST)。
语义分析:对抽象语法树进行遍历,计算出表达式的值。
"""
"""
Interpreter 类:
text:待解析的表达式。
pos:当前解析的位置。
current_token:当前的 token。
"""
class Interpreter:
def __init__(self, text):
self.text = text
self.pos = 0
self.current_token = None
def error(self): #error:当遇到语法错误时,抛出异常。
raise Exception('Invalid syntax')
def get_next_token(self): #get_next_token:获取下一个 token,并更新 pos 和 current_token。
#辅助理解
print(self.current_token)
print('寻找下一个token')
text = self.text
if self.pos >= len(text):
self.current_token = None
return
self.current_token = text[self.pos]
self.pos += 1
def eat(self, token_type): #eat:检查当前 token 是否与预期类型匹配,如果不匹配则抛出异常。
if self.current_token == token_type:
self.get_next_token()
else:
self.error()
print('检查类型')
def factor(self): #处理数字:如果当前 token 是数字,则将其转换为整数并返回。
token = self.current_token #处理括号:如果当前 token 是左括号,则递归调用 expr 计算括号内的表达式,然后返回结果。
if token == '(':
self.eat('(')
result = self.expr()
self.eat(')')
return result
elif token.isdigit():
result = int(token)
self.get_next_token()
return result
else:
self.error()
print('处理数字或括号')
def term(self): #处理乘法和除法:首先计算因子,然后处理连续的乘法和除法运算。
result = self.factor()
while self.current_token in ('*', '/'):
op = self.current_token
self.get_next_token()
right = self.factor()
if op == '*':
result *= right
elif op == '/':
result /= right
print('处理乘除')
return result
def expr(self): #处理加法和减法:首先计算项,然后处理连续的加法和减法运算。
result = self.term()
while self.current_token in ('+', '-'):
op = self.current_token
self.get_next_token()
right = self.term()
if op == '+':
result += right
elif op == '-':
result -= right
print('处理加减')
return result
def main():
while True:
try:
text = input('calc> ')
except EOFError:
break
if not text:
continue
interpreter = Interpreter(text)
interpreter.get_next_token()
result = interpreter.expr()
print(result)
if __name__ == '__main__':
main()
代码整体结构与功能
这段代码实现了一个简单的算术表达式解释器。它的主要功能是:
- 接收用户输入的算术表达式:通过
input()
函数获取用户输入的表达式字符串。 - 词法分析:将输入的字符串分割成一个个有意义的符号(token),比如数字、运算符等。
- 语法分析:根据语法规则,判断输入的表达式是否合法,并构建抽象语法树(AST)。
- 语义分析:对抽象语法树进行遍历,计算出表达式的值。
解释器风格的特点
- 灵活性:可以通过修改语法规则和添加新的函数来扩展解释器的功能。
- 易于调试:逐条解析执行,方便定位错误。
- 动态性:可以在运行时修改代码或数据。
局限性
- 效率较低:每次执行都需要重新解析和解释代码。
- 功能有限:相对于编译型语言,解释器的功能通常较弱。
2、规则系统风格
规则系统是一种基于规则的系统,它通过一系列规则来定义系统的行为。这些规则通常由条件和动作组成,当条件满足时,就会触发相应的动作。规则系统非常适合用来解决那些需要根据大量规则进行决策的问题,比如专家系统、配置管理系统等。
规则系统示例:判断一个学生是否能通过考试
#判断一个学生是否能通过考试
"""
Rule类:
condition: 表示规则的条件,是一个函数,输入为事实字典,返回一个布尔值。
action: 表示规则的动作,也是一个函数,输入为事实字典,执行相应的操作。
evaluate: 用于评估规则,如果条件满足,则执行动作。
"""
class Rule:
def __init__(self, condition, action):
self.condition = condition
self.action = action
def evaluate(self, facts):
if self.condition(facts):
self.action(facts)
"""
RuleBasedSystem类:
rules: 存储所有的规则。
facts: 存储所有的事实。
add_rule: 添加一条规则。
assert_fact: 添加一个事实。
infer: 进行推理,不断循环评估所有规则,直到没有新的事实产生。
"""
class RuleBasedSystem:
def __init__(self):
self.rules = []
self.facts = {}
def add_rule(self, rule):
self.rules.append(rule)
def assert_fact(self, fact, value):
self.facts[fact] = value
def infer(self):
changed = True
while changed:
changed = False
for rule in self.rules:
rule.evaluate(self.facts)
"""
condition_pass 和 condition_fail 定义了通过和不通过的条件。
action_pass 和 action_fail 定义了通过和不通过的动作。
"""
# 定义规则
def condition_pass(facts):
return facts['score'] >= 60
def action_pass(facts):
print("恭喜你,你通过了考试!")
def condition_fail(facts):
return facts['score'] < 60
def action_fail(facts):
print("很遗憾,你没有通过考试。")
# 创建规则系统
rbs = RuleBasedSystem()
rbs.add_rule(Rule(condition_pass, action_pass))
rbs.add_rule(Rule(condition_fail, action_fail))
# 设定事实
rbs.assert_fact('score', 65)
# 进行推理
rbs.infer()
代码改进和扩展:
这个例子只是一个简单的演示,你可以根据实际需求进行改进和扩展。例如:
- 增加更多的规则: 可以定义更多的规则来处理更复杂的情况。
- 使用更复杂的条件: 条件可以是多个事实的组合,也可以使用逻辑运算符。
- 使用更复杂的动作: 动作可以是调用其他函数、修改数据库等。
- 引入不确定性: 可以使用概率或模糊逻辑来处理不确定的信息。