ad

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

网友投稿 128 2023-11-07

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

7.1.2 操作列表

列表对象上定义了很多操作,最典型的就是查找、修改、增加和删除。这一小节 分别来研究一下如何实现这些功能。

1. 取下标

列表的取下标非常类似于 C 语言中的数组,它是通过中括号语法进行索引的, 代码如下:

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

使用中括号和下标的形式取得列表中的指定元素,这种语法我们第一次遇到。 与以前相同,通过 show_file 工具查看一下这种数组下标的语法会被翻译成怎样的 字节码,如下所示:

第4行,赫然又是一个新的字节码:BINARY_SUBSCR 。 在这个字节码之前,已 经把列表lst 和整数0加载到了栈顶。这个字节码的意义是取出列表 Ist 的 第 0 项 , 并将结果送入栈顶,它是 subscript 的缩写。

实际上,除了列表有取下标操作以外,string 对象也支持取下标操作,未来还会 遇到自定义类型中也可以支持取下标的操作。因此,这就有必要在 HiObject 对象体 系中引入取下标操作了。先来定义 HiObject 中的 subscr 方法,然后再扩展到 HiList 和 HiString 类中去,代码如下:

在 Object 类中,subscr 的真正实现转移到它的 Klass 中去了。在 Klass 中,sub- scr 会是一个虚函数,通过多态机制保证了不同类型的对象可以调用相应的 subscr 方法。例如,list 类型的实现代码如下:

1 //object/klass.hpp

2 class Klass{

3 private:

4

5 public:

6

7 virtual HiObject *subscr (HiObject*x,HiObject*y)(return 0;)

8 };

9

10 //object/hiList.hpp

11 class ListKlass:public Klass{

12 private:

13

14 public:

15

16 virtual HiObject*subscr(HiCbject*x,HiObject*y);

17 };

18

19 //object/hiList.cpp

20 HiObject*ListKlass::subscr(HiObject*x,HiObject*y){

21 assert(x&&x>klass()==(Klass*)this);

22 assert(y &&y>klass()==(Klass*)IntegerKlass::get_instance());

23

24 HiList *lx =(HiList*)x;

25 HiInteger*iy =(HiInteger*)y;

26

27 return lx->inner_list()>get(iy->value());

28

在上述代码的第22行,检查了第二个参数的类型,也就是下标,在 list 中,它必 须是整型。如果不是整型的话,虚拟机就会直接退出。实际上,Python 的行为是会 抛出异常,到目前为止,异常还没有完整地实现,所以先采用“报错退出”这种处理方 式。除此之外其他代码就比较简单了,不多做解释。

最后,还要在Interpreter 中添加 BINARY_SUBSCR 的实现。只需要将栈顶的码清单7.2所示。

void Interpreter::run(CodeObject*codes)(

2 _frame =new FrameObject(codes);

3 while(_frame->has_more_codes())(

4 unsigned char op_code =_frame>get_op_code();

5

6 FunctionObject*fo;

7

8 switch(op_code)

9 · ·

10 case ByteCode::BINARY_SUBSCR:

11 v=POP();

12 W =POP();

13 PUSH(w->subscr(v));

14 break;

15

16

17

18

至此,本小节开始的那个测试就可以正确执行了。

在完成了list 的 subscr 操作之后,为string 添加相应的操作就很简单了。整个 流程的框架已经搭起来了,只需要在StringKlass 中添加 subscr 即可,代码如下:

string 的取下标操作与列表的取下标操作几乎一样,唯一不同的是,subscr 方法 的返回值,在list 中直接从列表中读出就可以了,在 StringKlass 中则必须先创建一 个新的 string 对象。我们使用了带有长度参数的构造方法来创建这个字符串对象。 这个构造方法的具体实现,请读者参考第五章字符串的实现部分。

2. 查 找

在 Python 中,查找列表是否包含了某个对象,通常使用in 关键字使用in 关键字可以判断“hello” 是否在列表中。和以前一样,使用 show_file 工 具查看这个例子的字节码:

注意第4行的字节码:COMPARE_OP 。 这个字节码我们已经很熟悉了,在第四 章已经为这个字节码实现了是否相等和比较大小等操作。我们知道,这个字节码是 带有参数的,它的参数的意义是比较操作符的类型,比如4代表大于,0代表小于,2 代表等于。在这一节,COMPARE_OP 带了一个新的参数:6,括号里的注释也标明 了这个参数代表in。首先,要先把in操作添加到COMPARE

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

上一篇:跟着一起学《Excel VBA跟卢子一起学 早做完 不加班 基础入门版》_1.2 excel一键操作完成的来源
下一篇:《Python+3自动化软件发布系统》Django 2实战_了解Python的更好方法_2.6.3 UrlConf 的路由分发
相关文章

 发表评论

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

×