详解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回调函数用法实例分析
May 09 Python
使用Python内置的模块与函数进行不同进制的数的转换
Mar 12 Python
Python numpy 常用函数总结
Dec 07 Python
Python下载网络文本数据到本地内存的四种实现方法示例
Feb 05 Python
Python多版本开发环境管理工具介绍
Jul 03 Python
Django视图扩展类知识点详解
Oct 25 Python
Python爬取豆瓣视频信息代码实例
Nov 16 Python
Python实现将蓝底照片转化为白底照片功能完整实例
Dec 13 Python
Python中pyecharts安装及安装失败的解决方法
Feb 18 Python
浅谈Python __init__.py的作用
Oct 28 Python
Python实现随机爬山算法
Jan 29 Python
Python环境搭建过程从安装到Hello World
Feb 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&mysql(五)
2006/10/09 PHP
php日期转时间戳,指定日期转换成时间戳
2012/07/17 PHP
解析百度搜索结果link?url=参数分析 (全)
2012/10/09 PHP
使用PHP编写发红包程序
2015/07/22 PHP
PHP的Yii框架中移除组件所绑定的行为的方法
2016/03/18 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
2018/06/06 PHP
JS event使用方法详解
2008/04/28 Javascript
jQuery对指定元素中指定字符串进行替换的方法
2015/03/17 Javascript
javascript实现超炫的向上滑行菜单实例
2015/08/03 Javascript
jquery.validate使用详解
2016/06/02 Javascript
jQuery fadeOut 异步实例代码详解
2016/08/18 Javascript
jquery实现超简单的瀑布流布局【推荐】
2017/03/08 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
2017/04/12 Javascript
bootstrap 设置checkbox部分选中效果
2017/04/20 Javascript
微信小程序中form 表单提交和取值实例详解
2017/04/20 Javascript
JS实现DOM节点插入操作之子节点与兄弟节点插入操作示例
2018/07/30 Javascript
详解nuxt路由鉴权(express模板)
2018/11/21 Javascript
微信小程序事件对象中e.target和e.currentTarget的区别详解
2019/05/08 Javascript
vue 地图可视化 maptalks 篇实例代码详解
2019/05/21 Javascript
谈谈我在vue-cli3中用预渲染遇到的坑
2020/04/22 Javascript
react组件基本用法示例小结
2020/04/27 Javascript
Vuex中的Mutations的具体使用方法
2020/06/01 Javascript
《Python之禅》中对于Python编程过程中的一些建议
2015/04/03 Python
详解python基础之while循环及if判断
2017/08/24 Python
使用apidocJs快速生成在线文档的实例讲解
2018/02/07 Python
深入解析Python小白学习【操作列表】
2019/03/23 Python
在python中,使用scatter绘制散点图的实例
2019/07/03 Python
python实现中文文本分句的例子
2019/07/15 Python
Python爬虫破解登陆哔哩哔哩的方法
2020/11/17 Python
武汉世纪畅想数字传播有限公司.NET笔试题
2014/07/22 面试题
学生会竞选自荐信
2013/10/12 职场文书
大专应届生个人简历的自我评价
2013/10/15 职场文书
村创先争优活动总结
2014/08/28 职场文书
奉献家乡演讲稿
2014/09/16 职场文书
六一儿童节开幕词
2015/01/29 职场文书
小学生教师节广播稿
2015/08/19 职场文书