详解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脚本实现分析dns日志并对受访域名排行
Sep 18 Python
python字典键值对的添加和遍历方法
Sep 11 Python
Python中字典和集合学习小结
Jul 07 Python
使用django-crontab实现定时任务的示例
Feb 26 Python
Python网络编程之TCP套接字简单用法示例
Apr 09 Python
python3+pyqt5+itchat微信定时发送消息的方法
Feb 20 Python
python实现微信防撤回神器
Apr 29 Python
TensorFlow自定义损失函数来预测商品销售量
Feb 05 Python
在pycharm中实现删除bookmark
Feb 14 Python
在PyCharm中遇到pip安装 失败问题及解决方案(pip失效时的解决方案)
Mar 10 Python
Spark处理数据排序问题如何避免OOM
May 21 Python
python flappy bird小游戏分步实现流程
Feb 15 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
IIS6.0+PHP5.x+MySQL5.x+Zend3.0x+GD+phpMyAdmin2.8x通用安装实例(已经完成)
2006/12/06 PHP
PHP中的替代语法简介
2014/08/22 PHP
jQuery Mobile + PHP实现文件上传
2014/12/12 PHP
PHP中SSO Cookie登录分析和实现
2015/11/06 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
javascript中clone对象详解
2014/12/03 Javascript
JavaScript中的对象序列化介绍
2014/12/30 Javascript
js实现可兼容IE、FF、Chrome、Opera及Safari的音乐播放器
2015/02/11 Javascript
JavaScript实现的简单拖拽效果
2015/06/01 Javascript
纯JavaScript实现的分页插件实例
2015/07/14 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
Vue.js每天必学之构造器与生命周期
2016/09/05 Javascript
jQuery点击导航栏选中更换样式的实现代码
2017/01/23 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
jquery.masonry瀑布流效果
2017/05/25 jQuery
jfinal与bootstrap的登出实战详解
2017/11/27 Javascript
JS实现的简单折叠展开动画效果示例
2018/04/28 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
2019/03/07 Javascript
vue3.0 搭建项目总结(详细步骤)
2019/05/20 Javascript
js数组中去除重复值的几种方法
2020/08/03 Javascript
vue路由切换时取消之前的所有请求操作
2020/09/01 Javascript
[40:19]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.18
2020/12/19 DOTA
Python自动化运维_文件内容差异对比分析
2017/12/13 Python
pycharm远程linux开发和调试代码的方法
2018/07/17 Python
基于nexus3配置Python仓库过程详解
2020/06/15 Python
pymongo insert_many 批量插入的实例
2020/12/05 Python
matplotlib之属性组合包(cycler)的使用
2021/02/24 Python
Tory Burch美国官方网站:美国时尚生活品牌
2016/08/01 全球购物
Made in Design意大利:现代家具、名家灯具和装饰
2020/10/27 全球购物
车间主管岗位职责
2013/11/14 职场文书
毕业典礼主持词大全
2014/03/26 职场文书
文秘自荐信
2014/06/28 职场文书
小班上学期个人总结
2015/02/12 职场文书
会计求职自荐信
2015/03/26 职场文书
检讨书模板大全
2015/05/07 职场文书
JavaWeb 入门篇:创建Web项目,Idea配置tomcat
2021/07/16 Java/Android