首页 > 编程语言 >Python解释器

Python解释器

时间:2023-01-11 09:47:34浏览次数:58  
标签:LOAD 解释器 code CONST Python FAST dis

Python解释器

目录

Python程序的运行

首先执行词法分析、语法解析和编译,将Python代码转化成_code object_,这是解释器可以理解的指令,而Python解释器要做的就是解释_code object_中的指令。

字节码

>>> import dis
>>> def add() -> int:
...     a = 1
...     b = 2
...     return a + b
...
>>> dis.dis(add)
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  3           4 LOAD_CONST               2 (2)
              6 STORE_FAST               1 (b)

  4           8 LOAD_FAST                0 (a)
             10 LOAD_FAST                1 (b)
             12 BINARY_ADD
             14 RETURN_VALUE

由此可以得到,字节码的结构为行号 | 指令在函数中的偏移 | 指令 | 指令参数 | 实际参数值

在得到的字节码中,LOAD_CONST, STORE_FAST, LOAD_FAST等是Python的指令名称。除此之外,操作变量的字节码还有

  • LOAD_CONST:加载const变量
  • LOAD_FAST:加载局部变量的值
  • STORE_FAST:保存值到局部变量
  • LOAD_GLOBAL:加载全局变量的值
  • STORE_FAST:保存值到全局变量
  • BUILD_LIST:创建列表
  • BUILD_MAP:创建空字典
  • STORE_NAME:初始化字典内容

_code object_

>>> add.__code__
<code object add at 0x000001DF9F9EC030, file "<stdin>", line 1>
>>> list(add.__code__.co_code)
[100, 1, 125, 0, 100, 2, 125, 1, 124, 0, 124, 1, 23, 0, 83, 0]
>>> dis.opname[100]
'LOAD_CONST'
>>> dis.opname[125]
'STORE_FAST'
>>> add.__code__.co_consts
(None, 1, 2)
>>> add.__code__.co_varnames
('a', 'b')

__code__是与函数对象关联的code object,co_code是它的字节码(指令和指令参数的索引)co_varnames是定义过的变量,co_consts是给a,b的赋值,

基本控制语句

顺序语句

  2           0 LOAD_CONST               1 (1)

以第一行字节码为例,Python解释器解释这一行字节码,执行“从code object的co_consts中取索引值为1的数值1存入数据栈中”这一操作,然后逐条执行之后的字节码指令。

条件语句

想要实现条件和循环结构,需要让解释器能够在指令中跳转。例如:

>>> import dis
>>> def condition() -> str:
...     a = 1
...     if a <= 3:
...             return "<="
...     else:
...             return ">"
...
>>> dis.dis(condition)
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  3           4 LOAD_FAST                0 (a)
              6 LOAD_CONST               2 (3)
              8 COMPARE_OP               1 (<=)
             10 POP_JUMP_IF_FALSE       16

  4          12 LOAD_CONST               3 ('<=')
             14 RETURN_VALUE

  6     >>   16 LOAD_CONST               4 ('>')
             18 RETURN_VALUE
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE
>>> list(condition.__code__.co_code)
[100, 1, 125, 0, 124, 0, 100, 2, 107, 1, 114, 16, 100, 3, 83, 0, 100, 4, 83, 0, 100, 0, 83, 0]

源代码中的条件语句被编译成LOAD_FAST, LOAD_CONST, COMPARE_OP, POP_JUMP_IF_FALSE,比较a和3之后,满足条件继续执行,如果不满足,POP_JUMP_IF_FALSE让解释器跳转到索引为16的指令。

循环语句

与条件语句类似,循环语句也需要实现指令跳转。例如:

>>> import dis
>>> def loop() -> int:
...     a = 1
...     while a <= 3:
...             a = a + 1
...     return a
...
>>> dis.dis(loop)
  2           0 LOAD_CONST               1 (1)
              2 STORE_FAST               0 (a)

  3     >>    4 LOAD_FAST                0 (a)
              6 LOAD_CONST               2 (3)
              8 COMPARE_OP               1 (<=)
             10 POP_JUMP_IF_FALSE       22

  4          12 LOAD_FAST                0 (a)
             14 LOAD_CONST               1 (1)
             16 BINARY_ADD
             18 STORE_FAST               0 (a)
             20 JUMP_ABSOLUTE            4

  5     >>   22 LOAD_FAST                0 (a)
             24 RETURN_VALUE
>>> list(loop.__code__.co_code)
[100, 1, 125, 0, 124, 0, 100, 2, 107, 1, 114, 22, 124, 0, 100, 1, 23, 0, 125, 0, 113, 4, 124, 0, 83, 0]

在这段字节码中,解释器先执行比较,满足条件继续执行,JUMP_ABSOLUTE让解释器跳转到循环开始的位置,条件不满足时,POP_JUMP_IF_FALSE让解释器跳转到索引值为22的指令结束循环。

除了上文提到的存储变量值的数据栈之外还需要使用调用栈,Python程序的每个作用域都有一个帧,当函数被调用时,这个函数对应的帧会被压入调用栈,当这个函数执行完毕并返回时,这个帧就出栈(帧在Python代码执行过程中动态的创建和销毁)

另外,为了处理循环、异常处理等控制流块,还需要创建块栈。调用栈中的每一帧都有它的数据栈和块栈。

参考资料

  1. 字节码:https://docs.python.org/zh-cn/3.8/library/dis.html

  2. CPython:https://github.com/python/cpython

  3. Byterun:https://github.com/nedbat/byterun

标签:LOAD,解释器,code,CONST,Python,FAST,dis
From: https://www.cnblogs.com/euler0525/p/17042857.html

相关文章

  • python文件头部#/usr/bin/env python和#coding:utf-8的作用
    一、声明作用#!/usr/bin/python#!/usr/bin/envpython#coding:utf-8以上代码,放在python文件的头部,仅作为声明作用如果是python3,则改为python3#!/usr/bin/envpython......
  • Python将str转为int型或float型
    string转化为int型int转化为string型string转化为float型float转化为string型含小数点的string分割为整数部分和小数部分string转化为int型string转化为int型——10进制:in......
  • Python+ Flask轻松实现Mock Server
    每天进步一点点,关注我们哦,每天分享测试技术文章本文章出自【码同学软件测试】码同学公众号:自动化软件测试,领取资料可加:magetest码同学抖音号:小码哥聊软件测试1、什么是......
  • python利用matplotlib生成迷宫
    起因我想要写一个项目叫python迷宫游戏,需求是玩家能和机器对抗率先走出迷宫,至少要有两个等级的电脑。慢慢来,首先迷宫游戏需要有一个迷宫并展示出来,这便是这篇博客的目的......
  • python操作mysql数据库,增删查改等需要执行后加commit()
    p1:关于commit方法第一感觉是这个方法只用来提交“数据”,比如插入数据、更新数据需要在execute()后面跟上一个commit();现在看来,commit()方法需要跟在增(insert)、删(delete)、......
  • MySQL UPDATE:修改数据-更新数据-在原有表基础上增加列--python
    使用UPDATE语句修改单个表,语法格式为:UPDATE<表名>SET字段1=值1[,字段2=值2…][WHERE子句][ORDERBY子句][LIMIT子句]语法说明如下:<表名>:用于指定要......
  • Python爬虫-第三章-4-利用BeautifulSoup模块爬取某网壁纸图库图片
    思路:1.提取子页面链接2.访问子链接页面,提取下载地址3.访问下载地址下载内容到本地#DemoDescribe:数据解析bs4importtimeimportrequestsimportrandomimportstringfr......
  • Python 发电子邮件示例
    #!/usr/bin/envpython#-*-coding:utf-8-*-#python3.5importreimportosimportsmtplibfromioimportStringIOfromvalidate_emailimportvalidate_emailfromema......
  • 【Python】查看Python版本和CUDA版本
    【Python】如何查看自己的Python和CUDA版本查看Python版本1.首先Win+R输入cmd打开终端2.输入python-V查询Python版本查看CUDA版本输入nvcc-V......
  • 2023-01-10 python基础2
    迭代器第一次接触,类似于for循环个人感觉(虽然写了这么个例子,但是不知道迭代器用在哪里,等以后写写代码看看)class迭代器:def__init__(self,num):self.num......