学习笔记——跟着A Python Interpreter Written in Python写Python

Python解释器 – 执行Python程序最后的一步

解释器执行程序之前,Python会执行其他三个步骤:词法分析、语法分析与语义分析、编译。这三步将Python源代码转换为code object解释器的工作就是解释执行code object中的指令(字节码)

  • Python解释器是一个虚拟机,模拟真实计算机的软件(模拟CPU主要功能)
    • CPU主要功能功能:取指,译码,执行
  • code object:Python源代码转换为字节码(指令的集合)存放在其中,还会存有常量、变量、位置参数、关键字参数等信息
  • 词法分析,语法分析和语义分析,编译:有对应的词法分析器,语法分析器,编译器来一起生成code object

编写一代解释器

我们给出的指令不是真正的字节码,是用dis库反汇编出来的,真正的字节码是二进制的给电脑看的
我们从一个小的解释器开始,计算两个数的合。只能理解三个指令:
LOAD_CONST:将co_consts元组对应下标的数压栈
BINARY_ADD:将栈顶元素与下一个元素弹出,进行加法,得到的结果重新压栈
RETURN_VALUE:将栈顶元素弹出并作为返回值返回
现阶段指令如何产生我们不关心,假设编译器已经生成指令,我们来研究指令如何执行
一个指令与内存中的一条二进制一样,分为两个部分,操作码、与操作数。操作码为该指令要做什么如加法、减法。操作码为需要的数据去哪里找。
所以生成的指令集包含字节码与需要用到的数据
请添加图片描述

假设7+5生成如下指令

what_to_execute = {
    "instructions": [("LOAD_CONST", 0),  # the first number
                     ("LOAD_CONST", 1),  # the second number
                     ("BINARY_ADD", None),
                     ("RETURN_VALUE", None)],
    "co_consts": (7, 5) }

注意:为什么不讲数值嵌入指令中呢:如果我们加的不是数字,而是字符串。而且这种设计也意味着我们只需要对象的一份拷贝,比如这个加法 7 + 7, 现在常量表 "co_consts"只需包含一个7
Python的解释器是一个基于栈的解释器,执行所有的指令,数据的交互都是通过操作栈来完成的,栈的特点就是先进后出,可以用Python的列表来表示。

class Interpreter:  
	def __init__(self):  
		self.stack = []                      
	  
	def LOAD_CONST(self, number):  
		 # LOAD_CONST:将co_consts对应下标值压栈
		self.stack.append(number)            
	  
	def RETURN_VALUE(self):  
		# RETURN_VALUE:将栈顶元素弹出,将返回值返回
		answer = self.stack.pop()  
		print(answer)  
	  
	def BINARY_ADD(self): 
		# 将栈顶元素与下一个元素弹出,进行相加,结果压栈 
		first_number = self.stack.pop()  
		second_number = self.stack.pop()  
		result = first_number + second_number  
		self.stack.append(result)

完成了解释器所理解的指令,还差最重要的一步,一个能把所有指令和数据结合在一起并执行的方法。一个循环,遍历指令,来完成执行。

def run_code(self, par_what_to_execute):
	# 获取指令
	instructions = par_what_to_execute["instructions"]
	# 获取指令所需数据    
	numbers = par_what_to_execute["co_consts"]  
	for each_step in instructions:  
		instruction, argument = each_step  
		if instruction == "LOAD_CONST":  
		number = numbers[argument]  
		self.LOAD_CONST(number)  
		elif instruction == "BINARY_ADD":  
		self.BINARY_ADD()  
		elif instruction == "RETURN_VALUE":  
		self.RETURN_VALUE()

完成了,我们创建一个解释器对象,然后用前面定义的 7 + 5 的指令集来调用run_code

interpreter = Interpreter()  
interpreter.run_code(what_to_execute)
# 输出为 12

我们上面写的这个解释器只要给出合适的指令集,不需要改变任何代码,就可以执行多个数的加法。可以试一试 10 + 13 + 20

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值