ad

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_7.1 列表

网友投稿 113 2023-11-07

【摘要】 本书摘自《自己动手写 Python 虚拟机》一书中第7章,第1节,海纳编著。

7.1 列 表

7.1.1 列表的定义

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_7.1 列表

Python 中的列表很像数组操作,可以支持对元素的插入、添加和删除等操作。 实际上,Python 的 list 和 STL 中的 vector 非常相似。不同的是,Python 的 list 允许

它的元素是不同类型的。以一个例子来说明 list的特性,代码如下:

1

2

3

4

lst =[1,"hello"]

#result is [1,'hello']

print lst

可以看到,上面的代码中定义了一个列表,这个列表包含了两个元素。第一个元 素是整数1,第二个元素是字符串“hello”; 第二行代码输出这个列表。

通过show_file 工具,能观察到 Python 为了定义列表引入了新的字节码。本小 节的任务就是实现这些定义列表所用的字节码定义列表并打印,所使用的字节码如上面所列,其中绝大部分的字节码都已经见

过了,我们的虚拟机里也已经实现好了。唯一一个新的字节码是 BUILD_LIST 。 在 BUILD_LIST 之前有两个 LOAD_CONST 指令,分别把整数1、字符串“hello” 送到 栈顶。BUILD_LIST 指令是带有参数的,它的参数就代表了操作数栈上有多少个元 素是列表中的内容。在这个例子里,参数是2,这就表示应该从栈上取出两个对象, 并以这两个对象为参数去创建一个新的列表,然后把这个列表再放到操作数栈顶。

如何实现 list 呢?回忆之前的虚拟机实现中,有一个数据结构ArrayList 也可以 进行数据的增删查改。只需对 ArrayList 进行封装,将其包装成一个 HiObject 的子 类即可,代码如下:

1 class ListKlass:public Klass{

2 private:

3 ListKlass();

4 static ListKlass*instance;

5

6 public:

7 static ListKlass*get_instance();

8

9 virtual void print(HiObject*obj);

10 };

11

12 class HiList:public HiObject(

13 friend class ListKlass;

14

15 private:

16 ArrayList*_inner_list;

17

18 public:

19 HiList();

20 HiList(ObjList ol);

21 ArrayList*inner_list()(return_inner_list;)

22

23 int size() {return_inner_list->size();}

24 void append(HiObject*obj) {_inner_list->add(obj);}

25 HiObject*pop() (return_inner_list->pop();}

26 HiObject*get(int index) (return_inner_list ->get(index);}

27 void set(int i,HiObject*o) {_inner_list>set(i,o);}

28 HiObject*top() {return get(size()-1);}

29 >;

在上面的代码里,定义了一个新的类型 HiList, 它是 HiObject 的子类。在

作,最终都转化成了对 ArrayList 的操作。这些操作包括:

(1)append, 向列表的尾部添加一个元素;

(2)pop, 将列表的最后一个元素删除,并返回这个元素;

(3)get, 给定下标,取出列表中相应的值;

(4)set, 给定下标,将列表中相应的值设为输入参数的值;

(5)top, 取列表的最后一个元素,但不删除。

如何将这些方法与Python 字节码相联系是下一节的主要任务。这里还是将注 意力集中到 ListKlass 的实现上。在本书的设计理念中,所有与类型相关的操作都 会在 Klass 中实现。为了支持打印列表,要在 ListKlass 中实现 HiList 的 print 方 法,代码如下:

1 HiList::HiList(){

set_klass(ListKlass::get_instance());

3 _inner_list =new ArrayList();

4 )

5

6 HiList::HiList(ObjList ol){

7 set_klass(ListKlass::get_instance());

8 _inner_list =ol;

9}

10

11 ListKlass*ListKlass::instance =NULL;

12

13 ListKlass*ListKlass::get_instance(){

14 if(instance ==NULL)

15 instance =new ListKlass();

16

17 return instance;

18 }

19

20 ListKlass::ListKlass(){

21

22

23 void ListKlass::print(HiObject*x){

24 HiList *lx =(HiList*)x;

25 assert(1x &&lx->klass()==(Klass*)this);

26

27 printf("[");

28

29 int size =lx->_inner_list->size();

if(size>=1)

1x>_inner_list->get(0)>print();

for(inti=1;i

printf(",");

1x>_inner_list>get(i)>print();

36

printf(")");

上述代码的第1~9行,定义了 HiList 的构造方法。在构造方法里,将 klass 设 置 为ListKlass, 这个操作和 Hilnteger 、HiString 等如出一辙,不再详细解释。

第11~21行,实现了ListKlass 单例类,关于单例模式,我们也反复使用多次了 不必过多解释。

第23~38行,定义了ListKlass 的 print 方 法 。print 方法是定义在 HiObject 中 的虚方法。ListKlass 中 的 print 方法仅仅是为了实现对 HiList 对象的打印。它的 逻辑比较简单,打印左中括号以后,就将 list 中的所有元素逐个取出并且调用它的 print 方法。

构建好了 HiList 这个基础设施以后,字节码 BUILD_LIST 的实现就水到渠成 了,如代码清单7.1所示。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《Excel VBA+SQL数据管理与应用模板开发》_工作效率UP!_3.1 SQL 主要语句
下一篇:《自己动手写 Python 虚拟机》_更理解虚拟机的意义_1.1 编程语言的发展
相关文章

 发表评论

暂时没有评论,来抢沙发吧~

×