shhgs <[email protected]>
Mar 7, 2007 2:07 PM
class和type的区别 打一个比方。在学OO的时候,老师会说,class就是一个模子,往里面浇铁水之后,就有了对象了。 OK,这里就有问题了。你写的代码,相当于工程师设计的图纸,而图纸是没有办法往里面浇铁水的,你得把图纸变成模子,才能往里面浇东西。 于是,你写的代码,定义了一个算法。这个算法别称为class。 你的class,交给type,type根据你的class,加工出一个模子,然后你就可以往里面浇铁水生成instance了。这个type就类似于工厂的生产能力,工艺流程,或者。。。在编程的时候,这个type是语言的一种机制,能把你用代码定义的算法,也就是class,解释成能生成object,或者说instance(其实这个术语更好)的一种object(在解释meta programming的时候,一定要区分instance和object。这也是为什么,我曾经宣称,OOP应该是面向客体的编程。)。 OK,Py的type有很多,你import types然后dir(types)可以看到很多。具体而言,每种type都是一种组织内存的方式。比如说,Python内部表示类的对象,同表示instance的对象,其内部构造是不同的。那么这个内部构造是怎么定义的呢?就是这个type定义的。比如,每个instance都应该有一个dict,有表示其parent的tuple,此外还有初始化的时候,生成的parent类的对象(这部分具体应该问Robert Chen,我菜了)。而class里面可能就没有这么些东西。反正这就是type定义的。 接下来的东西,你可以去看Py in a nutshell了。Alex把福尔摩斯推理的最重要的一页给撕了。我也是琢磨了半天,最后在看Programming Ruby的时候搞懂的。现在给你补齐,应该能看懂了。
Mar 7, 2007 10:13 PM
type和class绝对不同。
Python里面的所有对象,都是由type制造的。相应的type制造一个blanket的对象,然后解释器再根据你的源代码,往这个blanket的对象里面塞东西。
空白的class object是由types.ClassType或者types.TypeType创建的。而你写的代码,会先在一个dict里面运行,然后塞进这个blanket的class object里面。
>>> code = """ def func(self) : print "blah, blah, blah" """ >>> d = dict() >>> exec(code, d) >>> import types >>> old_class = types.ClassType("OldClass", (), d) >>> o = old_class() >>> o.func() blah, blah, blah >>> new_class = types.TypeType("NewClass", (), d) >>> o = new_class() >>> o.func() blah, blah, blah * instance一一样。先由types.InstanceType创建一个blanket的instance。在new * class里面,这一步可以通过__new__控制。而所谓的meta * programming正是在这个__new__里面搞花样。blanket的instance创建完毕,再把dict绑定过去。这样,一个instance就有了。
Mar 7, 2007 11:56 PM
OK, class和type有不同的理解。我这里先解释一下我的定义。 class是指你源代码里面 ---------------------------------- class MyClass : def blah() : ........ ---------------------------------- 用这种语法定义的类。 而type是指 ------------------------------------- >>> import types >>> dir(types) .................. ------------------------------------- 你看到的这些东西。 这两者截然不同。他们之间的关系,我用如下一个比喻解释。 你是一个工程师。你现在设计一个很复杂的系统,里面用到了OOP的解决方案。你定义了各种对象,然后让他们相互传消息解决问题。 但是你只是在图纸上设计了这些对象,定义了它们的接口。你不能直接往图纸里浇铁水,你得有模子。 OK,你拿着图纸,找到一家叫Py的工厂。这个工厂拿到图纸之后说,没问题,我给你造。于是它根据图纸造一个模子(class object)。制造模子的时候,工厂用的是自己的生产工具(types.ClassType,或者tpyes.TypeType,看你用new class还是old class)。 但是光有模子没用,你要的是解决问题,你得让工厂再按照你的图纸生产处一些能收发消息的对象。 Py工厂说,没问题,有了模子还愁instance吗。只是我们的模子只能我们自己用。于是它再备料。这次出场的是InstanceType。你可以把InstanceType想成一种类似塑料一样的东西。原本你以为工厂是会往模子里浇铁水的,结果它的模子只能浇这种塑料。Anyway,东西做出来了,也能收发消息了,你就能让程序跑起来解决问题了。
Mar 8, 2007 9:13 AM
type和class是两个空间的东西。 class是用户空间的概念。当然这个用户是Py的程序员。 type是在实现Py解释器的过程当中,其OO设计的一个层次。 这两个空间在99.99%的情况下是没有交集的,只是在meta programming的时候碰了头。 你举的这个例子确实有些两难。这个meta class对程序员来说,是一个class,对Py解释器来说,又可以当作type来用。Anyway,能写出这种代码的人,还在乎这种区别吗? 现在不是解答问题吗。要解答问题,就得给一个内恰的,明确的,清晰的解释。而这个解释,很大程度上又取决于如何定义type和class。我觉得你的分类标准并不适合初学者。你所说的,type和class没有区别,实际上在写Py代码的时候并不实用。用户使用class就能自定义class,但是他们为什么不能自定义type?如果两者完全没有差别,为什么又要有type,而且还无处不在。这些问题都很实际,而且也不是你所说的"两者没有区别"所能解释的。相反我的划分方式,把class归到用户空间,把type归到Py解释器的实现,我觉得还是比较清楚的,也是能自圆其说的。 我无意在这个地方和你辩论。读者要听谁的,请自己选择。
Mar 8, 2007 9:35 AM
new class object的type是object。 反正不管是new还是old,type都是Py解释器内部的东西,class都是用户空间的东西。而知道type之间的相互关系,只是在meta programming的时候有用。
Mar 8, 2007 10:31 AM
Py的type是不能自定义的。你只能继承已有的types里面的type。要想自定义一个type,比如像Perl, Ruby那样,用1..3表示一个Range,你就得用C。从这个角度来讲,不管new还是old的class,都不是type。 你前面写的,class int(object)是笔误。我还以为可以这样继承int了。MyInt虽然继承了int,但是看不出有什么用。其实Python的meta programming也就type有用。 new class object的type其实还是object。这个肯定是不错的。object是所有object的base type。其实new class object在初始化的时候,采用的方式同old class的大同小异。都是调用 一个方法,生成一个blanket的instance,然后往里面塞东西。所不同的是,old class用的是InstanceType,而new class用的是class object的__new__方法。 Python 2.2之前的OO实现还是很清楚的,现在这个实现,思路很混乱。主要是为了要过渡到Py 3000。这个type和object之间的鸡和蛋的关系实在同Py的优雅不沾边。Py 3000取消了type之后,meta programming应该更容易了。