>>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表示二进制01100101。部分ASCII码对照表如下图所示。

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

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

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

字节码分析

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

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

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

>>>importopcode
>>>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,ReturnswithTOStothecallerofthefunction

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

>>>importdis
>>>dis.dis(s_code)
10LOAD_NAME0(a)
3LOAD_CONST0('b')
6INPLACE_ADD
7STORE_NAME0(a)
10LOAD_CONST1(None)
13RETURN_VALUE

完整代码:

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

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

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

热门推荐

1 50岁人生祝福语简短
2 春节新年祝福语简短霸气
3 谢谢老师出差祝福语简短
4 班级里元旦祝福语简短
5 灵活就业祝福语大全简短
6 牛年祝福语简短和表情
7 女孩生日说说祝福语简短
8 祝福语简短精辟人生感悟
9 学生的简短祝福语大全
10 小学毕业父母简短祝福语
11 幼儿生日祝福语模板简短
12 新娘妈妈的祝福语简短
13 邻居聚会祝福语大全简短
14 十条祝福语简短
15 给同学祝福语的简短
16 过年祝福语简短祝妈妈
17 祝女儿简短祝福语大全
18 恩师诗词祝福语简短大全