Excel 名称框概述-英雄云拓展知识分享
113
2023-11-07
【摘要】 本书摘自《自己动手写 Python 虚拟机》一书中第7章,第1节,海纳编著。
7.1 列 表
7.1.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
17
18 public:
19 HiList();
20 HiList(ObjList ol);
21 ArrayList
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~