`
geradle
  • 浏览: 13320 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

补发:澄清Python的Open class

阅读更多
在这里对我在Why not python?这帖子中的一些错误的看法进行澄清,避免造成误导。
那个帖子地址为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
分享到:
评论
12 楼 yymoth 2006-11-18  
想不到limodou 也喜欢来java社区看看..呵呵.
11 楼 yymoth 2006-11-18  
正在学习中...
10 楼 limodou 2006-11-17  
http://www.python.org/download/releases/2.3/mro/

简单地说就是:

1. 在实例范围内查找
2. 在类范围内查找
3. 在基类范围内查找,这里因为python是可以多重继承的,因此对于基类有一个查找策略,比较复杂,具体看文档
4. 找不到则调用类的 __getattr__ 方法, new style class 还有一个 __getattribute__
5. 还没有则抛出异常
9 楼 geradle 2006-11-17  
试验了一下,确实如Charon所说。现在看来Python完全可以实现Open class的功能。

另外,我非常想知道Python在对象的属性和方法调用时的搜索顺序是什么样的。
记得以前potain还是谁发了一个关于Ruby的,不知道有没有非常了解的Python的人也发一个。
8 楼 limodou 2006-11-17  
icetortoise 写道
连limodou都逛到javaeye来了...


我经常来,只不过看到的基本上都是ruby的东西。但看到有人对于python不是很了解,忍不住回复一下,不想大家对python有更多的误解。
7 楼 charon 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

不就可以了。
6 楼 icetortoise 2006-11-17  
连limodou都逛到javaeye来了...
5 楼 limodou 2006-11-17  
实例属性与类属性是不同的。上面例子将一个函数赋给了实例属性,自然不会是class方法的使用方式。如果你想把一个函数变成类方法,需要这样做:

class A:
    pass

def funca(self, name):
    print name
    
A.func = funca

a = A()
a.func("limodou")


绑定对象不同,效果自然不同。
4 楼 geradle 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,的一种表现!
3 楼 charon 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也可以这么做,但没确认过)

2 楼 geradle 2006-11-16  
qiezi 写道
在那边回复了一段,怎么被删了呢?白写了啊。。删除也要先把回复弄过来嘛。建议不要删除记录,用个字段作个标记就行了。
不知道为什么前面我发的那个帖子一打开IE,FF就挂了,所以删除了,害怕害人,所以删除了。那就麻烦你再写一遍了。
1 楼 qiezi 2006-11-16  
在那边回复了一段,怎么被删了呢?白写了啊。。删除也要先把回复弄过来嘛。建议不要删除记录,用个字段作个标记就行了。

相关推荐

    道路运输从业人员从业资格证件换发、补发、变更登记表.pdf

    2. 补发:如果从业资格证件遗失、损毁或者无法辨认,从业者需要通过此表向管理部门报告并申请补发新的证件。在申请过程中,可能需要提供相关的证明材料,如报警回执或损坏证件的照片等。 3. 变更登记:当从业者的...

    《出生医学证明》补发制度.doc

    当这份证明因各种原因遗失、被盗或者损坏时,就需要按照特定的程序进行补发。以下是对《出生医学证明》补发制度的详细说明: 1. 补发范围与条件: - 适用范围:补发仅限于1996年1月1日之后出生的婴儿,因为在此...

    Python视频教程 百度云下载

    Python视频教程,文件内含百度云下载链接,请自行下载观看,链接失效时可联系邮箱补发,谢谢,赶快下载吧,即下即用~

    文件补发申请表(DOC格式).doc

    在IT管理领域,文件补发申请表是一种重要的文档管理工具,尤其在企业内部,用于规范文件的使用、丢失和补发流程。以下是基于"文件补发申请表(DOC格式).doc"标题和描述所涉及的知识点的详细说明: 1. **文件管理**...

    文件补发申请表(表格模板、DOC格式).doc

    文件一旦遗失、损坏或过时,其补发流程的效率与规范性将直接影响组织的运行效率。因此,一套标准化的文件补发申请表模板对于维护文件的完整性、保障组织正常运作至关重要。 文件补发申请表的制定,首先需要对原有...

    长春理工大学公文补发审批单.docx

    8. **补发部门负责人签字**:作为补发部门的负责人,需要对补发的必要性和合理性进行把关,并在审批单上签字确认。 9. **主管校领导签批**:在某些情况下,可能需要更高级别的领导进行审批,以确保补发的合理性和...

    附件6道路运输从业人员从业资格证件换发、补发、变更登记表.docx

    文档标题和描述中提到的是一个关于道路运输从业人员从业资格证件的换发、补发和变更登记的表格,这个过程涉及到的主要是交通运输行业的规定和流程。以下是相关知识点的详细说明: 1. **道路运输从业人员从业资格**...

    文件补发申请表.doc

    "文件补发申请表.doc" 提供了一种系统化的方式来处理丢失或损坏的文件,确保业务流程的连续性和信息的可追溯性。下面将详细阐述文件补发申请表的相关知识点: 1. **文件编号**: 文件编号是每个文档独有的标识,...

    道路运输从业人员从业资格证件换发、补发、变更登记表.docx

    综上所述,《道路运输从业人员从业资格证件换发、补发、变更登记表》是一份非常重要的文件,它不仅规定了证件换发、补发、变更的具体流程,还明确了各方的责任与义务。对于道路运输从业人员来说,正确填写并提交该...

    文件补发申请表_1.doc

    "文件补发申请表"是这一过程中的关键工具,它主要用于跟踪和控制组织内部的文件分发、丢失或损坏时的补发需求。以下是关于这个主题的详细解释: 1. **文件补发申请表**: 文件补发申请表是一种正式的记录,用于...

    股票补发申请书(DOC格式).doc

    股票补发申请书是股东在丢失或毁损股票证书后,为了恢复其股东权益而向上市公司提交的重要文件。本文将详细解析股票补发申请书的相关知识点,并探讨其在管理中的重要性。 首先,股票作为股东持有公司所有权的证明,...

    股票补发申请书.doc

    股票补发申请书作为股份制企业中的一项重要财务操作文件,承载着股东与公司间权益保护的重要使命。在股东股票遗失或毁损的情形下,股票补发申请书不仅是股东请求补发股票的书面证据,也是公司按照法定程序审核并实施...

    教师资格证补发换发申请表.pdf

    教师资格证补发换发申请表.pdf

    专业技术资格证书补发登记表、遗失补发申请表.doc

    专业技术资格证书补发登记表、遗失补发申请表.doc

    股票遗失补发申请书模板.doc

    股票遗失补发申请书是投资者在不慎丢失股票凭证时,为了恢复其股东权益而向上市公司或证券公司提交的重要文件。以下将详细解释这个过程及相关知识点: 1. **股票凭证的重要性**:股票凭证是股东拥有公司股份的法律...

    补发学生证申请书.doc

    【补发学生证申请书】 在学生的学习生活中,学生证是一个非常重要的证件,它不仅是学生身份的证明,还涉及到图书借阅、校内消费、乘坐公共交通等多方面的权益。因此,当学生证丢失时,及时补办是非常必要的。这篇...

    股票补发申请书(表格模板、DOC格式).doc

    股票补发申请书是股东在丢失或毁损股票证书时,为了恢复其持有权益而向上市公司或证券交易所提交的重要文件。这份申请书涉及到的管理知识主要包括以下几个方面: 1. **股票凭证的重要性**:股票凭证是股东对公司...

    01—04文件补发申请表.doc

    【文件补发申请表及其重要性】 在企业管理中,文件管理是至关重要的环节,它涉及到公司的信息流通、决策依据和法规遵循。"01—04文件补发申请表.doc"是一个专门用于处理文件丢失、损坏或需要更新情况的标准化表格,...

Global site tag (gtag.js) - Google Analytics