分享
 
 
 

面向对象的python(二)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

开始学习python的时候,看了一些教程和资料,都觉得在面向对象编程这一方面讲得比较零散,自己也就总觉得不得要领。直到看到了Oreilly出的Python in the Nutshell,英文版,特别是Charpter5: Object-Oriented Python,才开始明白一点点东西。这本书,对章节的编排非常合理,而且不光教你how还教你why,觉得受益匪浅。

看的过程中,自己陆续的记下一些东西,有对书的部分翻译,有自己的体会和测试代码。

翻译中,有少部分是直接翻译,大部分其实只是自己的意译,还添油加醋加上了自己的一些说明。毕竟,我的目的是为了把问题弄懂,不想去做那么多hard translation反让人如坠迷雾。于是想汇成一篇,就有了这篇文章。文章的安排,基本上和Python in the Nutshell的Charpter5相同,但内容要短得多。

Wilson Sun

----------------------------------------------------------------------------------------------------------------

1.1 新型对象(New-Style Classes)

在python的2.2和2.3版中,若对象直接或间接地继承了python的内建类型的对象,那么它就是新型对象。

“经典”往往是对旧事物的尊称,既然从2.2版开始推出新型对象,肯定是有种种好处的,所以该尽量用新型对象。

1.1.1 内建类型:object

从python的2.2开始,object是一种内建类型,它也是所有其它内建类型和新型对象的超类。

继承object的对象,需要重载下面方法:

_ _new_ _

_ _init_ _

_ _delattr_ _

_ _getattribute_ _

_ _setattr_ _

_ _hash_ _

_ _repr_ _

_ _str_ _

1.1.2 类级方法(Class-Level Methods)

类级方法是新型对象的特征之一,有两类:静态方法和对象方法。

1.1.2.1 静态方法(Static methods)

静态方法不存在bound和unbound的问题,可以直接调用。用staticmethod声明一个静态方法,如:

class AClass(object):

def astatic( ): print 'a static method'

astatic = staticmethod(astatic)

anInstance = AClass( )

AClass.astatic( )

1.1.2.2 类方法(Class methods)

可以在类的内部和类的实例上调用类方法。用classmethod声明,如:

class ABase(object):

def aclassmet(cls): print 'a class method for', cls._ _name_ _

aclassmet = classmethod(aclassmet)

class ADeriv(ABase): pass

bInstance = ABase( )

dInstance = ADeriv( )

ABase.aclassmet( ) # prints: a class method for ABase

bInstance.aclassmet( ) # prints: a class method for ABase

ADeriv.aclassmet( ) # prints: a class method for ADeriv

dInstance.aclassmet( ) # prints: a class method for ADeriv

类方法的第一个参数,就是调用这个方法的对象。

1.1.3 新型对象

新型对象也具有所有经典对象的特征,但它们还有更为独特的特征,_ _init_ _和_ _new_ _

1.1.3.1 _ _init_ _

一个新型对象C,它会直接或间接地继承object中的_ _init_ _方法,如果你不在C当中重载_ _init_ _方法的话,你传递给C的_ _init_ _方法任何参数都会被python忽略。

为了避免乱传参数,建议:即使不想在_ _init_ _做任何事,也该重载_ _init_ _方法,如:

class C(object):

def __init__(self): pass

这样,如果错误地向_ _init_ _传递了参数,python就会抛出一个异常。

1.1.3.2 _ _ new_ _

所有新型对象都有一个静态方法:_ _new_ _。

假设有一个新型对象C,现在你要创建C的一个实例x,那么你会写:

x = C(23)

执行过程是:python首先调用C中的_ _new_ _方法,_ _new_ _会返回一个实例,若检测过后该实例的确是C的实例,那么_ _init_ _会被调用,若_ _new_ _返回的实例不是C的实例,那么这个实例将不会被初始化(_ _init_ _)。这一过程和下面的代码等价:

x = C._ _new_ _(C, 23)

if isinstance(x, C): C._ _init_ _(x, 23)

你也可以自己在C的内部重载它的_ _new_ _方法,这种重载不需要用staticmethod来声明。

_ _new_ _方法可以用来返回不同的实例,可以用这种方式来实现Factory工厂模式,还可以实现singleton单态模式。

1.1.4 新型对象的实例

经典对象的实例中的所有特性,在新型对象的实例中也同样具备,新型对象实例还具备一些与之不同的特性。

1.1.4.1 属性(properties)

这里说的“属性”,是和方法相对的。在对象内部定义属性的时候,用python的内建类型:property。示例如下:

class Rectangle(object):

def _ _init_ _(self, width, heigth):

self.width = width

self.heigth = heigth

def getArea(self):

return self.width * self.heigth

area = property(getArea, doc='area of the rectangle')

上例中,area就是Rectangle的属性,由于只定义了get方法,所以它是只读属性。doc是属性的docstring参数,docstring的作用非常类似于注释,但和注释相比,它可以在运行时被使用,这时它的一大优点。

使用property的语法如下:

attrib = property(fget=None, fset=None, fdel=None, doc=None)

属性操作

代码示例

Python的实现

读取

n = x.attrib

返回property中fget函数值

赋值

x.attrib = 54

将值传入perperty中fset函数

删除

del x.attrib

调用fdel函数

在经典对象模型中,如果要实现上面的代码,要这样写:

class Rectangle:

def _ _init_ _(self, width, heigth):

self.width = width

self.heigth = heigth

def getArea(self):

return self.width * self.heigth

def _ _getattr_ _(self, name):

if name= ='area': return self.getArea( )

raise AttributeError, name

def _ _setattr_ _(self, name, value):

if name= ='area':

raise AttributeError, "can't bind attribute"

self._ _dict_ _[name] = value

1.1.4.2 _ _slots_ _

_ _slots_ _的作用和_ _dict_ _一样,用来存放实例的所有方法和属性。_ _dict_ _是字典(dict)类型,而_ _slots_ _是元组(tuple)类型,所以用_ _slots_ _会更节约内存,这也是使用它的唯一目的。要注意的是,一旦使用_ _slots_ _,那么原先的_ _dict_ _就没有作用了。

如果一个对象会同时产生百万级数目的实例,用_ _slots_ _会起到节约内存的目的,如果只是几千个实例,那么没必要。

还需要注意的是:实例中的_ _slots_ _不会被子类继承。

示例:

class OptimizedRectangle(Rectangle):

_ _slots_ _ = 'width', 'heigth'

1.1.4.3 _ _getattribute_ _

对实例属性的引用,都通过object中_ _getattribute_ _方法来实现。你也可以重载该方法来获得某些特殊的效果。例如,你不想list中的append方法被调用,就可以这样:

class listNoAppend(list):

def _ _getattribute_ _(self, name):

if name = = 'append': raise AttributeError, name

return list._ _getattribute_ _(self, name)

那么,每当x.append被调用的时候,都会出现异常。

1.1.4.4 Per-instance methods

1.1.5 新型对象中的继承

在继承这一方面,和经典对象相比,新型对象最大区别就是可以继承自内建类型的对象,而且python中是允许多重继承的。

1.1.5.1 方法的解析顺序

当存在继承关系的时候,python会到一个对象的基类(base class)中去查找方法或属性,特别是当存在多重继承关系的时候,查找的顺序是怎样的呢?这种查找顺序,被称为解析顺序(resolution order)。

假设有类A,它直接继承自B和C(顺序为:B,C),B和C又都继承自D。

经典对象模型和新型模型对象的解析顺序为下图所示:

经典对象模型的解析顺序是:左边优先,再深度优先。所以它的解析顺序是:先A-B-D-C-D。

新型对象模型的即席顺序是:A-B-C-D-object

写程序的时候,经典对象模型的这种解析顺序可能会产生一些问题,所以新型对象中更改了解析顺序,会先解析同级的基类。

1.1.5.2 超类调用

当重载(override)一个方法的时候,我们往往会对超类的同名方法做一些操作,但在多重继承的情况下,python目前的方法解析顺序并不完美。

看下面代码:

class A(object):

def met(self):

print 'A.met'

class B(A):

def met(self):

print 'B.met'

A.met(self)

class C(A):

def met(self):

print 'C.met'

A.met(self)

class D(B,C):

def met(self):

print 'D.met'

B.met(self)

C.met(self)

d=D()

d.met()

代码执行结果如下:

D.met

B.met

A.met

C.met

A.met

可以看到,A中的met被调用了两次。如果才能保证超类中的同名方法只被调用一次呢?这可以用python2.2中的super来解决,super是一种新的内建类型。调用super(aclass,obj)会返回obj的超类。

上面的代码可以做如下的修改:

class A(object):

def met(self):

print 'A.met'

class B(A):

def met(self):

print 'B.met'

super(B,self).met( )

class C(A):

def met(self):

print 'C.met'

super(C,self).met( )

class D(B,C):

def met(self):

print 'D.met'

super(D,self).met( )

注:tuple这个词,看到有多种翻译。觉得MS的Sql Server 2000联机手册中,把它译为“元组”,于是自己都采用这种翻译。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有