注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

互联网产品经理的窝

梦想社:一个人为了梦想,始终没有停下自己的脚步

 
 
 

日志

 
 

【Python 笔记】变量·类型·对象(三)  

2011-12-03 01:00:15|  分类: python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

转自别人博客的,想查找第一出处,但始终无果(N多博客都有,都无人写转字)。

感谢第一作者的辛勤劳动~


从(二)到(三)的跨度好大,拖了好久 T_T 其实是前段时间太忙了,实验报告流啊、网站换届啊、志愿者中心啊,不应该找借口,赎罪忏悔……

话说在笔记(二)总结了 Python 的对象模型,神马都是对象啊,是对象就有属性啊。基于这个前提之下,才有 Python 的“面向对象”模型,也就是类似 Java 的“对象”。

首先 Python 定义的类,就已经是一个对象(类似函数定义)。

>>> class Spam(object):
    pass

>>> print Spam
<class '__main__.Spam'>
>>> dir(Spam)
['__class__''__delattr__''__dict__''__doc__''__format__''__getattribute__''__hash__''__init__','__module__''__new__''__reduce__''__reduce_ex__''__repr__''__setattr__''__sizeof__''__str__','__subclasshook__''__weakref__']
>>>

于是这个类是一个对象意味着神马呢?意味着这个类可以有自己的属性,也可以像 Java 一样定义方法。而方法,在这里实质上是类的属性,属性的值是函数对象。

>>> egg  = Spam()
>>> egg
<__main__.Spam object at 0x028722F0>
>>> egg is Spam
False
>>> egg.__class__ is Spam
True
>>> isinstance(egg,Spam)
True
>>>

这里没有 new 操作符,实例化一个类只需要对类进行 call ,就像 call 一个函数一样。可以见到,这个 call 的动作产生了一个新的对象 egg 也就是 Spam 的实例。

好吧,这个类没有任何内容,是没有意义的。现在来创建一个有意义的类。

>>> class Student(object):
    def __init__(self,name):
        self.name = name

        
>>> me = Student('tonyseek')
>>> print me
<__main__.Student object at 0x0289D950>
>>> print me.name
tonyseek
>>> print me.__dict__
{'name''tonyseek'}
>>> print me.__class__.__dict__
{'__dict__': <attribute '__dict__' of 'Student' objects>, '__module__''__main__''__weakref__': <attribute'__weakref__' of 'Student' objects>, '__doc__': None, '__init__': <function __init__ at 0x0289EBF0>}
>>>

有木有!?有木有!?【Python 笔记】变量·类型·对象(三) - 梦想社 - 梦想社

构造函数 __init__ 其实是类的一个属性成员,和实例的属性一样都保存在自己的 __init__ 里面。

而事实上,Python 中类和实例的关系,是泛化关系。也就是说,实例是类的子对象。__dict__ 属性用于保存属性,实例中已经复写了。

再来个特写对比:

>>> dir(Student)
['__class__''__delattr__''__dict__''__doc__''__format__''__getattribute__''__hash__''__init__','__module__''__new__''__reduce__''__reduce_ex__''__repr__''__setattr__''__sizeof__''__str__','__subclasshook__''__weakref__']
>>> dir(me)
['__class__''__delattr__''__dict__''__doc__''__format__''__getattribute__''__hash__''__init__','__module__''__new__''__reduce__''__reduce_ex__''__repr__''__setattr__''__sizeof__''__str__','__subclasshook__''__weakref__''name']
>>>

而我们的参数 self 事实上指向的就是一个类的实例对象(因为一切皆引用)。一开始觉得 Python 很奇怪的一点,是所有的类成员方法都要用 self 来作为第一个参数,作用是类似 Java/C++ 的 this 指针,指向当前实例。其实从原理来看就不奇怪了:


看,二者是等价的。调用一个对象的时候,实质上是把这个对象作为 self 参数,传到绑定在类上的函数中。

再说到前面所说的“实例是类的子类”,上真相:

>>> class M2(object):
    spam = 'ok'
    def __init__(self):
        print self.spam
        self.spam = 'oh'
        print self.spam

        
>>> m2 = M2()
ok
oh
>>> print M2.spam
ok
>>> print m2.spam
oh
>>>

在 __init__ 中,首先 print self.spam ,由于在 me2 对象并不存在 spam 属性,所以到 parent 的 M2 中,找到静态属性(类属性),print 出来是 ok;而在经过了赋值 self.spam = ‘oh’ 之后,me2 在自己对象中创建了 spam 属性(由于操作的是实例不是类,所以不会覆盖作为类属性的 spam),所以第二次 print 时,直接找到了 self 中的 spam 属性,所以 print 得到的是 oh 而不再是 ok。结果后面的 print M2.spam 我们可以看到,M2 的类属性还是保留了的,并没有被修改。

而基于 Python 这种邪魔歪道的特性,我们也能做一些邪魔歪道的事情。比如 open class,运行时改变一个类的定义。

>>> def new_init(self):
    self.spam = 'Spring Brother'

    
>>> M2.__init__
<unbound method M2.__init__>
>>> M2.__init__ = new_init
>>> m3 = M2()
>>> print m3.spam
Spring Brother
>>>

就这样活生生的把别的的成员,还是构造函数给换掉了。其实还可以邪恶多一点,把别人的父类换掉。后者是 Python 的 min-in (不知道是不是翻译成“混入”)的重要途径。

好吧,对象模型笔记到此结束。一个小白的笔记也只能写这么多。

继续研究我们可爱的又邪恶的 Python……

  评论这张
 
阅读(207)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017