详解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随机生成一个6位的验证码代码分享
Mar 24 Python
Python标准库之Sys模块使用详解
May 23 Python
Python实现更改图片尺寸大小的方法(基于Pillow包)
Sep 19 Python
itchat接口使用示例
Oct 23 Python
python实现抽奖小程序
Apr 15 Python
Python3实现汉语转换为汉语拼音
Jul 08 Python
TensorFlow实现简单的CNN的方法
Jul 18 Python
Pytorch实现各种2d卷积示例
Dec 30 Python
如何使用Python破解ZIP或RAR压缩文件密码
Jan 09 Python
Python使用requests模块爬取百度翻译
Aug 25 Python
python Matplotlib基础--如何添加文本和标注
Jan 26 Python
opencv 分类白天与夜景视频的方法
Jun 05 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
php 魔术方法使用说明
2009/10/20 PHP
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
PHPWind9.0手动屏蔽验证码解决后台关闭验证码但是依然显示的问题
2016/08/12 PHP
PHP中创建和编辑Excel表格的方法
2018/09/13 PHP
CSS和Javascript简单复习资料
2010/06/29 Javascript
两个Javascript小tip资料
2010/11/23 Javascript
检测jQuery.js是否已加载的判断代码
2011/05/20 Javascript
javascript之typeof、instanceof操作符使用探讨
2013/05/19 Javascript
jQuery检测鼠标左键和右键点击的方法
2015/03/17 Javascript
高性能JavaScript 重排与重绘(2)
2015/08/11 Javascript
jQuery web 组件 后台日历价格、库存设置的代码
2016/10/14 Javascript
JS Select下拉框(支持输入模糊查询)
2017/02/04 Javascript
jQuery 判断元素整理汇总
2017/02/28 Javascript
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
2017/09/20 jQuery
JavaScript实现QQ列表展开收缩扩展功能
2017/10/30 Javascript
bootstrap-Treeview实现级联勾选
2017/11/23 Javascript
JS实现点击复选框变更DIV显示状态的示例代码
2017/12/18 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
Python使用urllib模块的urlopen超时问题解决方法
2014/11/08 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
python如何实现int函数的方法示例
2018/02/19 Python
使用NumPy和pandas对CSV文件进行写操作的实例
2018/06/14 Python
Python读取Pickle文件信息并计算与当前时间间隔的方法分析
2019/01/30 Python
在Python中使用Neo4j的方法
2019/03/14 Python
Python3 中sorted() 函数的用法
2020/03/24 Python
python MultipartEncoder传输zip文件实例
2020/04/07 Python
Pycharm激活方法及详细教程(详细且实用)
2020/05/12 Python
Jupyter notebook如何实现指定浏览器打开
2020/05/13 Python
HTML5拖放API实现拖放排序的实例代码
2017/05/11 HTML / CSS
SmartBuyGlasses台湾:名牌眼镜,名牌太阳眼镜及隐形眼镜
2017/01/04 全球购物
食品安全检查制度
2014/02/03 职场文书
领导班子四风对照检查材料思想汇报
2014/09/26 职场文书
2014年社区卫生工作总结
2014/12/18 职场文书
2016年社区“6.26”禁毒日宣传活动总结
2016/04/05 职场文书
如何写好闭幕词
2019/04/02 职场文书
介绍一下28个JS常用数组方法
2022/05/06 Javascript