详解python字节码


Posted in Python onFebruary 07, 2018

Python对不可变序列进行重复拼接操作效率会很低,因为每次都会生成一个新的对象,解释器需要把原来对象中的元素先复制到新的对象里,然后再追加新的元素。

但是CPython对字符串操作进行了优化,因为对字符串做+=操作实在是太普遍了。因此,初始化str时会预留出额外的可扩展空间,从而进行增量操作的时候不会有复制再追加的这个步骤。

通过字节码研究一下这个过程。

>>> s_code = 'a += "b"'
>>> c = compile(s_code, '', 'exec')
>>> c.co_code
b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S'
>>> c.co_names
('a',)
>>> c.co_consts
('b', None)

得到的字节码是Bytes类型的。这里穿插一些Bytes类型的知识。

Bytes类型

b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S',b表示是Bytes类型。Bytes以二进制字节序列的形式记录数据,每一个字符就代表一个字节(8位)。比如上面的e表示二进制0110 0101。部分ASCII码对照表如下图所示。

但是,不是所有的字节都是可显示的,甚至有些字节无法对应到ASCII码上(因为ASCII码只定义了128个字符,而一个字节有256个)。比如0000 0000对应的ASCII是不可显示的、0111 1111没有对应的ASCII码。

为了表示这些无法显示的字节,就引入了\x符号,其表示后续的字符为16进制。如,\x00表示16进制的00,也就是二进制的0000 0000。

至此,所有字节都可被表示。

字节码分析

回到开始的代码。为了显示方便,将b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S'转为16进制来显示。

>>> c.co_code.hex()
'650000640000375a000064010053'

通过opcode.opname函数可以得到操作码所对应的操作指令

>>> import opcode
>>> opcode.opname[0x65]
'LOAD_NAME'

因此,完整的字节码可以解释为(TOS即top-of-stack,栈顶元素):

字节:位置,功能
65:0,LOAD_NAME
0000:参数,将co_names[0]的值,即a的值,压入栈
64:3,LOAD_CONST
0000:参数,将co_consts[0],即'b',压入栈
37:6,INPLACE_ADD,TOS = TOS1 + TOS
5a:7,STORE_NAME
0000:参数,co_names[0]=TOS,即将栈顶赋值给a
64:10,LOAD_CONST
0100:参数
53:13,RETURN_VALUE,Returns with TOS to the caller of the function

实际上借助dis函数可以直接获得可读的字节码:

>>> import dis
>>> dis.dis(s_code)
 1      0 LOAD_NAME        0 (a)
       3 LOAD_CONST        0 ('b')
       6 INPLACE_ADD
       7 STORE_NAME        0 (a)
       10 LOAD_CONST        1 (None)
       13 RETURN_VALUE

完整代码:

s_code = 'a += "b"'
c = compile(s_code, '', 'exec')
c.co_code
c.co_names
c.co_consts
c.co_code.hex()
import dis
dis.dis(s_code)

非常失败,对比了string和tuple的赋值字节码,并没有看出string的优化…

以上就是本次关于python字节码的相关知识点,感谢你对三水点靠木的支持。

Python 相关文章推荐
python求素数示例分享
Feb 16 Python
Python中使用glob和rmtree删除目录子目录及所有文件的例子
Nov 21 Python
使用beaker让Facebook的Bottle框架支持session功能
Apr 23 Python
Python实现基本线性数据结构
Aug 22 Python
Python中字符串的修改及传参详解
Nov 30 Python
Python中pillow知识点学习
Apr 30 Python
Pycharm配置远程调试的方法步骤
Dec 17 Python
python爬虫获取小区经纬度以及结构化地址
Dec 30 Python
如何利用python web框架做文件流下载的实现示例
Jun 02 Python
python 实现的IP 存活扫描脚本
Dec 10 Python
Python还能这么玩之用Python修改了班花的开机密码
Jun 04 Python
人工智能深度学习OpenAI baselines的使用方法
May 20 Python
Tensorflow之构建自己的图片数据集TFrecords的方法
Feb 07 #Python
python深度优先搜索和广度优先搜索
Feb 07 #Python
Python Flask基础教程示例代码
Feb 07 #Python
Python装饰器用法实例总结
Feb 07 #Python
使用apidocJs快速生成在线文档的实例讲解
Feb 07 #Python
Python自定义线程池实现方法分析
Feb 07 #Python
使用apidoc管理RESTful风格Flask项目接口文档方法
Feb 07 #Python
You might like
dede全站URL静态化改造[070414更正]
2007/04/17 PHP
用PHP实现维护文件代码
2007/06/14 PHP
PHP通过正则表达式下载图片到本地的实现代码
2011/09/19 PHP
PHP中可以自动分割查询字符的Parse_str函数使用示例
2014/07/25 PHP
php实现网站顶踩功能的完整前端代码
2015/07/19 PHP
JavaScript OOP类与继承
2009/11/15 Javascript
JavaScript Cookie显示用户上次访问的时间和次数
2009/12/08 Javascript
使用Java实现简单的server/client回显功能的方法介绍
2013/05/03 Javascript
js中单引号与双引号冲突问题解决方法
2013/10/04 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
jQuery插件multiScroll实现全屏鼠标滚动切换页面特效
2015/04/12 Javascript
PassWord输入框代码分享
2016/06/07 Javascript
javascript工厂模式和构造函数模式创建对象方法解析
2016/12/30 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
Python的Bottle框架中获取制定cookie的教程
2015/04/24 Python
用Python写一段用户登录的程序代码
2018/04/22 Python
Numpy之random函数使用学习
2019/01/29 Python
在python中用print()输出多个格式化参数的方法
2019/07/16 Python
调用其他python脚本文件里面的类和方法过程解析
2019/11/15 Python
python实现矩阵和array数组之间的转换
2019/11/29 Python
Django 用户登陆访问限制实例 @login_required
2020/05/13 Python
python爬虫中url管理器去重操作实例
2020/11/30 Python
纯CSS3编写的的精美动画进度条(无flash/无图像/无脚本/附源码)
2013/01/07 HTML / CSS
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
世界上最大的在线旅行社新加坡网站:Expedia新加坡
2016/08/25 全球购物
丝芙兰中国官方商城:SEPHORA中国
2018/01/10 全球购物
怎样创建、运行java程序
2014/08/01 面试题
Final类有什么特点
2012/04/25 面试题
简历中的自我评价怎么写
2014/01/29 职场文书
酒店优秀员工事迹材料
2014/06/02 职场文书
民事诉讼代理授权委托书范本
2014/10/08 职场文书
先进单位申报材料
2014/12/25 职场文书
详解Redis实现限流的三种方式
2021/04/27 Redis
教你怎么用Python处理excel实现自动化办公
2021/04/30 Python
Python编程根据字典列表相同键的值进行合并
2021/10/05 Python
java协程框架quasar和kotlin中的协程对比分析
2022/02/24 Java/Android