详解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检测主机存活端口及检查存活主机
Oct 12 Python
Python的装饰器使用详解
Jun 26 Python
基于并发服务器几种实现方法(总结)
Dec 29 Python
Python即时网络爬虫项目启动说明详解
Feb 23 Python
Python生成任意范围任意精度的随机数方法
Apr 09 Python
神经网络相关之基础概念的讲解
Dec 29 Python
Python实现的微信红包提醒功能示例
Aug 22 Python
Python多线程模块Threading用法示例小结
Nov 09 Python
使用python实现哈希表、字典、集合操作
Dec 22 Python
完美解决pycharm导入自己写的py文件爆红问题
Feb 12 Python
python的help函数如何使用
Jun 11 Python
opencv+pyQt5实现图片阈值编辑器/寻色块阈值利器
Nov 13 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小教程之实现双向链表
2014/06/12 PHP
详解PHP的Yii框架中自带的前端资源包的使用
2016/03/31 PHP
PHP实现支持CURL字符串证书传输的方法
2019/03/23 PHP
基于PHP实现邮箱验证激活过程详解
2020/10/28 PHP
JavaScript中this关键字使用方法详解
2007/03/08 Javascript
Javascript select控件操作大全(新增、修改、删除、选中、清空、判断存在等)
2008/12/19 Javascript
JavaScript 格式字符串的应用
2010/03/29 Javascript
web页面数据展示新想法(json)
2010/06/08 Javascript
用js判断页面刷新或关闭的方法(onbeforeunload与onunload事件)
2012/06/22 Javascript
浅谈轻量级js模板引擎simplite
2015/02/13 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
2015/03/03 Javascript
JS对字符串编码的几种方式使用指南
2015/05/14 Javascript
jquery对复选框(checkbox)的操作汇总
2016/01/13 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
2016/10/10 Javascript
Node.js中 __dirname 的使用介绍
2017/06/19 Javascript
vue.js,ajax渲染页面的实例
2018/02/11 Javascript
javascript变量提升和闭包理解
2018/03/12 Javascript
vue2单元测试环境搭建
2018/05/24 Javascript
详解js模板引擎art template数组渲染的方法
2018/10/09 Javascript
vue的keep-alive中使用EventBus的方法
2019/04/23 Javascript
在React中写一个Animation组件为组件进入和离开加上动画/过度效果
2019/06/24 Javascript
解决vue初始化项目一直停在downloading template的问题
2020/11/09 Javascript
Python的多态性实例分析
2015/07/07 Python
python3.6+django2.0开发一套学员管理系统
2018/03/03 Python
三星新西兰官网:Samsung新西兰
2019/03/05 全球购物
小学优秀班集体申报材料
2014/05/25 职场文书
工作求职自荐信
2014/06/13 职场文书
2014年新教师工作总结
2014/11/08 职场文书
2014年政协委员工作总结
2014/12/01 职场文书
MBA推荐信怎么写
2015/03/25 职场文书
太行山上观后感
2015/06/05 职场文书
《家世》读后感:看家训的力量
2019/12/30 职场文书
PHP基本语法
2021/03/31 PHP
javascript实现计算器功能详解流程
2021/11/01 Javascript
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis
VUE递归树形实现多级列表
2022/07/15 Vue.js