《PYTHON源码剖析》的第十二章:Python虚拟机中的类机制 http://blog.sina.com.cn/s/blog_75984e830100yf3i.html

《PYTHON源码剖析》的第十二章:Python虚拟机中的类机制

  (2011-09-13 15:59:04)
标签: 

杂谈

 

这一章主要讲到了Python中的类。其实在看完前面十一章后对于动态语言的理解已经深刻了不少了,所以对于类机制的疑问也主要是在于如何通过a=A()这样的语句去创建一个实例,然后去调用a中的方法。至于如对于基类的继承之类的内容其实不是很在意。

这一章主要可以分成三个方面,先是typeclass的转变,主要讲了基类和子类的关系,包括tp_dict这个字典的建立。然后是用户自定义的class的字节码的分析。最后是对于创建出来的实例去调用其中的方法时的字节码分析。

说实话第一方面讲的实在是太复杂了,看了两遍也仅仅能知道其讲了啥,但如果问我具体的细节,我还是答不出。不过我关心的也不是这一部分,所以知道其大概是啥样就足够了:之前的python中系统自定义的那些类称作TYPE。其和用户自定义的类有一个很大的不同就是用户自定义的类只能继承用户自定义的类,不能继承那些TYPE。所以Python的那些大牛们在考虑了好久后引入了tp_dict这个字典。正是这个字典的引入使得子类可以继承TYPE,并调用TYPE中的方法。

这一章的前半部分主要就是讲了tp_dict的建立。这里不得不提一个slot结构体,如果没有这个结构体,我们将不能知道__add__这样的方法所绑定的回调函数是什么。不过这个slot其实和PyFunctionObject一样,只是做个中间体,其最终会进化成一个descriptortp_dict中绑定的是descriptor而不是slot,一个重要的原因是slot并不是一个PyObject

对于用户自定义的class的建立其实和函数定义并无太大的区别。自定义的那些代码会的被编译成一个单独的PyCodeObject,当然啦其中的函数定义又会分别的被定义成一个一个小的PyCodeObject

那么如何用用户自己定义的class去定义一个instance呢?也很简单,看看这个字节码:

a=A()

LOAD_NAME 1 (A)

CALL_FUNCTION 0

STORE_NAME 2(a)

很明显,和函数的调用几乎完全没有差别。在符号表中找A,然后把A的字节码压入堆栈,然后CALL一下,最后把a保存起来就完事了。

看一下这里的CALL_FUNCTION,其会的沿着call_function->do_call->PyObject_Call-><class A>->tp_cal->A.tp_new,通过A.tp_new创建一个实例。当然啦,一般这里的A.tp_new肯定是继承自object这个class的。

这里还有一点要注意,用class创建class和用class创建insance用的是不同的tp_new

当然啦,在给新的实例分配好内存后还需要调用一下init这个初始化方法。这样我们的一个新的实例就建立了。

对于调用实例中的属性的内容,光是看其字节码是很容易的,和调用普通函数一模一样,无非是多了LOAD_ATTR这类字节码罢了,但其实没这么容易。具体的内容由于兴趣不在这里所以没有细看,

看看书中的一处总结:“抛开面向对象花里胡哨的外表,其实我们会发现,class对象其实就是一个名字空间,instance对象也是一个名字空间,不过这些名字空间通过一些特殊的规则联结在一起,是的符号的搜索过程变得复杂,从而实现了面向对象这种编程模式,仅此而已。”当然啦,这里所说的特殊规则的联结关系真的非常复杂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值