Python写的Python解释器(四)

编译自:http://www.aosabook.org/en/500L/a-python-interpreter-written-in-python.html 作者:Taavi Burns 翻译:鸿 如有翻译问题或建议,请公众号留言

真正的Python字节码 现在让进入真正的Python字节码中,从一个简单的函数开始:

>>> def cond():
...     x = 3
...     if x < 5:
...         return 'yes'
...     else:
...         return 'no'
...

Python会在运行时暴露其内部机制,使得可以从REPL中直接获得这些东西。对于函数cond,cond.__ code__是cond的代码对象,而cond.__code__.co_code是其对应的字节码。平时在编写Python代码时,这些属性几乎没有任何用处,但是现在就能发挥用途了。

>>> cond.__code__.co_code  # the bytecode as raw bytes
b'd\x01\x00}\x00\x00|\x00\x00d\x02\x00k\x00\x00r\x16\x00d\x03\x00Sd\x04\x00Sd\x00
   \x00S'
>>> list(cond.__code__.co_code)  # the bytecode as numbers
[100, 1, 0, 125, 0, 0, 124, 0, 0, 100, 2, 0, 107, 0, 0, 114, 22, 0, 100, 3, 0, 83, 
 100, 4, 0, 83, 100, 0, 0, 83]

仅仅只是print字节码,获得的就只是一系列字节信息。通过使用Python标准库中的dis模块(dis是一个字节码反汇编工具,可以翻译低级代码,例如汇编代码或字节码,并以人类可读的方式进行打印出来。),运行dis.dis时,就会给出cond函数传递的字节码的解释。

>>> dis.dis(cond)
  2           0 LOAD_CONST               1 (3)
              3 STORE_FAST               0 (x)
  3           6 LOAD_FAST                0 (x)
              9 LOAD_CONST               2 (5)
             12 COMPARE_OP               0 (<)
             15 POP_JUMP_IF_FALSE       22
  4          18 LOAD_CONST               3 ('yes')
             21 RETURN_VALUE
  6     >>   22 LOAD_CONST               4 ('no')
             25 RETURN_VALUE
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE

这是什么意思呢? 以第一条指令LOAD_CONST为例,第一列中的2给出的是Python源代码中的行号。第二列是字节码的索引,表示LOAD_CONST指令出现在零位。 第三列是指令本身,映射成人类可读的名称。第四列是该指令的参数。第五列表示这个参数的含义。继续再阅读这个字节码的前几个字节:[100,1,0,125,0,0]。这六个字节表示带参数的两条指令。可以使用dis.opname(将字节变成可理解字符串)来找出指令100和125对应的内容:

>>> dis.opname[100]
'LOAD_CONST'
>>> dis.opname[125]
'STORE_FAST'

第二个和第三个字节1,0是LOAD_CONST的参数,而第五个和第六个字节0,0是STORE_FAST的参数。就像前面的一样,LOAD_CONST需要知道在哪里找到要加载的常量,STORE_FAST需要找到存储的名称。(Python的LOAD_CONST与之前玩具解释器的LOAD_VALUE相同,LOAD_FAST与LOAD_NAME功能相同。)因此,这六个字节代表第一行代码,x = 3。(为什么每个参数需要使用两个字节?如果Python只使用一个字节来定位常量和名字,那么就只能有256个名字/常量与单个代码对象相关联,而使用两个字节,最多可以有256的平方,即65,536个)。

原文发布于微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文发表时间:2018-05-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python小屋

使用Python编写程序求解数独游戏答案

问题描述:数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在...

29730
来自专栏小樱的经验随笔

栈的存储结构的实现(C/C++实现)

存档 1 #include "iostream.h" 2 #include <stdlib.h> 3 #define max 20 4 typedef ...

32370
来自专栏Bingo的深度学习杂货店

Q62 Unique Paths

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the...

13220
来自专栏云霄雨霁

Java--通配符类型

20040
来自专栏xingoo, 一个梦想做发明家的程序员

汇编语言 手记8

栈有两个基本的操作:入栈和出栈 入栈:将一个新的元素放到栈顶 出栈:从栈顶取出一个元素 栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。 栈的操作规则:...

19950
来自专栏互联网技术栈

并发编程- java.util.concurrent用户指南

本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concur...

13130
来自专栏海纳周报

详解Python的is操作符

is 操作符是Python语言的一个内建的操作符。它的作用在于比较两个变量是否指向了同一个对象。 与 == 的区别 class A(): def __i...

43590
来自专栏Java大联盟

23种设计模式详解(五)

15130
来自专栏技术点滴

原型模式(Prototype)

原型模式(Prototype) 原型模式(Prototype) 意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。 应用:Java/C#中的...

19350
来自专栏chenssy

【死磕Java并发】-----J.U.C之阻塞队列:LinkedBlockingDeque

原文出处http://cmsblogs.com/ 『chenssy』 前面的BlockingQueue都是单向的FIFO队列,而LinkedBlockingDe...

36980

扫码关注云+社区

领取腾讯云代金券