该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-11-16
那个帖子地址为http://www.iteye.com/topic/33665?page=1 下面我把帖子大概描述一下: 首先: suninny 写道 要是Python也具备Closure(Block)的话我绝不会多瞧下Ruby。
接着: qiezi 写道 我倒觉得相比起ruby来,python只能算是中规中矩,没多少出彩的地方。 ruby我认为最强的地方是可以open一个类,扩充它。另一个强的地方是关键字,ruby的关键字很少,而且很多关键字可以当成方法名来用,限制很少,只要你愿意,可以随意地扩充ruby,把它看成是语言的一部分。 接着 geradle 写道 Python也具有Open Class 的特色的呀,你也可以实现这样的功能的。 class openclass(): def test(): print "test" open = openclass() open.test() def test1(): print "test1" open.test=test1 open.test() 还有那个method missing,python也有的。 最后 charon 写道 geradle的那个代码更多的是open object methods的功能,而且不像是python的代码,方法的第一个不是self啊 python在open class和open object methods的实现上有非常微妙的差别,主要就是这个self引起的。针对class的修改是含self的(需要声明,但调用时不需要给出,解释器自动添加这个参数),并且影响到这个类所有的对象(包括以前生成的);对object的属性的赋值是不带self的(解释器不会自动添加self参数),并且只影响到被修改的对象。 我估计和ruby的区别主要是python中function是first class造成的,而方法是函数的一个特例,从而产生绑定和非绑定的区别。但仔细思考之后,发现这个处理方式是自洽的 正是Charon的回复,让我觉得认真的学习一下Python method调用时候的是如何查找method的。结果不看不知道,一看下一跳,原来我原来关于python open class的想法是错误的。为什么是错误的呢? 先看看Ruby的Open class是怎么实现的。 引用 Reading further on Ruby's object-oriented features, I found out in Programming Ruby that: Classes are never closed: you can always add methods to an existing class. This applies to the classes you write as well as the standard, built-in classes. All you have to do is open up a class definition for an existing class, and the new contents you specify will be added to whatever's there. As a conseguence, you can always revise a method (changing its semantics) to an existing class no matter where you are. For instance, let consider the following example. 可以看出Ruby的Open Class是基于声明的。你在类定义的时候就改变了其方法或者Attribute的sematic. 然而Python中是在运行时改变的,应该不能成为Open class或者可以叫做Open object:).当然这个称呼是不恰当的。或许有人会居然python可以实现和ruby Open Class一样的功能,为何还要在乎概念呢。 有两个理由: Python中实现类似于Ruby Open Class的功能其实是Python把Function做为一等公民的另外一种表现,而不是所谓的Open Class. 为了介绍Python中Method与Function的差别,那样就可以更好的说明Charon前面试图说明的东西。 Python的Instance Object包含了data attributes & methods, data attributes好理解,那么Methods呢?Methods是该实例变量的类中定义的Functions.为什么要要强调这个呢?因为在Method和Function的调用过程中存在着以下差别。当你调用Function的时候,Function接受的参数就是你传递的参数。而当你调用Method的时候,实际参数是你传入的参数和instance object的引用,示例代码如下: >>>class method(): def test(self): print "method" >>> m = method() >>> m.test <bound method method.test of <__main__.method instance at 0x00B43BC0>> >>> m.test() method >>> method.test <unbound method method.test> >>> method.test(m) method >>> 下面再列举一段代码说明Method与Function的差别: >>> def test1(): print "test1" >>> test1 <function test1 at 0x00B2FCF0> >>> m.test=test1 >>> m.test <function test1 at 0x00B2FCF0> >>> m.test() test1 >>> method.test(m) method >>> 为什么上面的 m.test()没有出错呢,难得前面提到的Method调用是参数传递规则不对?上面的规则是对的,没有出错因为此处的 m.test()调用不是Method的调用,而是Function的调用。 为什么说此处是Function的调用而不是Method的调用呢? 因为在 m.test=test1执行的时候,我们实际上是为instance object m创造了一个data attribute,并把他赋值为function test1.所以 m.test()实际为Function的调用! 这里还关系到一个python的Method/Function的调用规则:当你通过instance object调用函数或者方法时,Python首先搜索该object的data attribute,再搜索其Class,base class。所以此处为Function调用!这个规则可以参看一篇文章http://www.informit.com/articles/article.asp?p=28672&seqNum=4&rl=1 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-11-16
在那边回复了一段,怎么被删了呢?白写了啊。。删除也要先把回复弄过来嘛。建议不要删除记录,用个字段作个标记就行了。
|
|
返回顶楼 | |
发表时间:2006-11-16
qiezi 写道 在那边回复了一段,怎么被删了呢?白写了啊。。删除也要先把回复弄过来嘛。建议不要删除记录,用个字段作个标记就行了。 不知道为什么前面我发的那个帖子一打开IE,FF就挂了,所以删除了,害怕害人,所以删除了。那就麻烦你再写一遍了。
|
|
返回顶楼 | |
发表时间:2006-11-16
geradle 写道 可以看出Ruby的Open Class是基于声明的。你在类定义的时候就改变了其方法或者Attribute的sematic. 然而Python中是在运行时改变的,应该不能成为Open class或者可以叫做Open object:).当然这个称呼是不恰当的。或许有人会居然python可以实现和ruby Open Class一样的功能,为何还要在乎概念呢。 其实,严格说来,ruby的open class和python的open class是一样的,都是基于运行时的。 因为,它们都没有一个(全局的)编译和连接阶段,所以不可能把某个地方的修改class定义的声明在该处代码未加载前应用到全局。 而动态语言的一个特点是,某段代码/模块只有在运行时才会被加载。 所以,即便是ruby代码的open class定义,如果这个类根本就没有被加载进来,是起不了作用的。而python的open class的做法,只要模块被import,自然也就修改了。这两者没有本质上的区别。 至于声明或者其他什么的处理方式,只有形式上的区分意义. python的open class无法搞定内置类型,这个是好处还是坏处,很难说。我个人倾向于好处,毕竟,一个使用内置类型的编程者,总是以最大的通用习惯来看待这些类型 但是,python的做法和ruby的一样,都可以做到一处修改影响到这个类的所有对象,所以都应当被归 之为open class(只不过python还有更加精确的施加于对象之上的做法,我估计ruby也可以这么做,但没确认过) |
|
返回顶楼 | |
发表时间:2006-11-17
charon 写道 至于声明或者其他什么的处理方式,只有形式上的区分意义.
我不这么认为,我认为至少在使用形式上是具有差别的。先贴段代码。 class Folder def initialize(name) @name = name @files = Array.new end def addFile(newFile) @files.push(newFile) end def list puts @name+":" for k in 0...@files.length puts "--"+@files[k] end end end #base semantics aFolder = Folder.new("reports") aFolder.list puts "here we're ..." #override class Folder def list puts @name+":" if @files.length == 0 raise "empty folder!" end for k in 0...@files.length puts "--"+@files[k] end end end #modified semantics aFolder = Folder.new("reports") aFolder.list puts "never reached!!" Ruby的Open class是居于声明的,这就带来一个好处,你可以和以前使用该类一样使用他的instance objects' methods,如果他没有改变方法的签名话。前面的Ruby代码说明,虽然我们修改了Class Folder的list方法,但是该类的list方法还是和以前一样调用。 在Python中你为了达到同样的目的,就是通过把Fucntion赋值给instance object的attribute(是否有其他方法,我不是很清楚)。由于你使用的Function定义于Class之外,如果你需要访问其instance Object的attributes的话,你需要在参数列表中包含其引用,但是Class的Method是不需要的,因为解释器会自动提供,所以就导致了参数的不一致。参看下面的代码: >>> class openclass(): def __init__(self,toprint="TEST"): self.val = toprint def test(self): print self.val >>> open = openclass() >>> open.test() TEST >>> def test(o): print o.val >>> open.test = test >>> open.test() Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> open.test() TypeError: test() takes exactly 1 argument (0 given) >>> open.test(open) TEST >>> 可以看出为了达到和Open Class的instance object的test method一样的效果,Function test的调用必须手动的传入instance object的引用,但是对于Method test这个是没有必要的。这就是我要强调的不通之处,这种不通之处似乎会造成Client的错误,所以我认为Python的该功能应当不可以称为Open Class。它只是Function is first class,的一种表现! |
|
返回顶楼 | |
发表时间:2006-11-17
实例属性与类属性是不同的。上面例子将一个函数赋给了实例属性,自然不会是class方法的使用方式。如果你想把一个函数变成类方法,需要这样做:
class A: pass def funca(self, name): print name A.func = funca a = A() a.func("limodou") 绑定对象不同,效果自然不同。 |
|
返回顶楼 | |
发表时间:2006-11-17
连limodou都逛到javaeye来了...
|
|
返回顶楼 | |
发表时间:2006-11-17
引用 在Python中你为了达到同样的目的,就是通过把Fucntion赋值给instance object的attribute(是否有其他方法,我不是很清楚)。由于你使用的Function定义于Class之外,如果你需要访问其instance Object的attributes的话,你需要在参数列表中包含其引用,但是Class的Method是不需要的,因为解释器会自动提供,所以就导致了参数的不一致。参看下面的代码: .... 可以看出为了达到和Open Class的instance object的test method一样的效果,Function test的调用必须手动的传入instance object的引用,但是对于Method test这个是没有必要的。这就是我要强调的不通之处,这种不通之处似乎会造成Client的错误,所以我认为Python的该功能应当不可以称为Open Class。它只是Function is first class,的一种表现! 兄弟,你难道光发帖不看帖? 实际上,在这个回帖里面已经说得很清楚了 http://www.iteye.com/post/172807 python可以针对instance object,对其属性赋function 也可以针对整个类,对这个类(实际上也就是个模块变量名)的属性赋值,这个时候就是自动搞定self的。 具体到你的这个例子 >>> class openclass(object): ... def __init__(self,toprint="TEST"): ... self.val = toprint ... def test(self): ... print self.val ... >>> def test(self): ... print 'aaaaa' + self.val ... >>> openclass.test = test >>> inst = openclass() >>> inst.test() aaaaaTEST 不就可以了。 |
|
返回顶楼 | |
发表时间:2006-11-17
icetortoise 写道 连limodou都逛到javaeye来了...
我经常来,只不过看到的基本上都是ruby的东西。但看到有人对于python不是很了解,忍不住回复一下,不想大家对python有更多的误解。 |
|
返回顶楼 | |
发表时间:2006-11-17
试验了一下,确实如Charon所说。现在看来Python完全可以实现Open class的功能。
另外,我非常想知道Python在对象的属性和方法调用时的搜索顺序是什么样的。 记得以前potain还是谁发了一个关于Ruby的,不知道有没有非常了解的Python的人也发一个。 |
|
返回顶楼 | |