分享
 
 
 

面向对象的python(一)

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

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

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

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

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

python是一种面向对象的编程语言。不过不象其它的面向对象的语言,python并不强迫你用面向对象的方法来写程序,它也允许你用面向过程的方式来写模块、函数等。

1.1 经典对象(classic class)

在2.1及其之前版本的python,只能用经典对象这种对象模型来编程。在2.2和2.3版本的python,经典对象也是默认的对象模型。

1.1.1 经典对象的一些特征:

l 你可以象调用函数一样的来调用一个对象。一旦调用,该对象的一个实例就被建立。

l 你可以随意地为对象内部的属性命名。

l 属性可以是数据类型,也可以是函数类型。

l 若属性(attribute)是函数类型,那么就把它看做对象的一个方法(method)。

l python为函数规定了一种特殊的命名方式,用前后两个下划线来包围函数名,例如:__methodName__。

l 对象可以继承。

1.1.2 对象声明

声明对象的语法:

class classname[(base-classes)]:

statement(s)

classname是函数名。

base-classes的值必须为对象,用逗号分隔,它相当于java中的超类(superclass)。

继承关系可以被传递,如果c1是c2的子类,c2是c3的子类,那么c1也是c3的子类。

内建函数issubclass(C1, C2)可以判断继承关系,若c1是c2的子类,那么函数返回true。由于任何类都被看作是自身的子类,所以若有类C,那么issubclass(C,C)返回true。

Def声明语法和class声明语法的区别:

Def声明时,冒号前面必须有括号,即使它本身没有任何参数;但class声明时,只有当class有其基类(base class)的时候,才需要在括号中写出其基类。

1.1.3 对象正文

1.1.3.1 对象内部的属性

在对象内部调用其属性,直接写其属性名称即可,如:

class C3:

x = 23

y = x + 22 # must use just x, not C3.x

但若在对象内部定义了方法,要在方法中调用对象中的其它属性,需要写属性的全名,如:

class C4:

x = 23

def amethod(self):

print C4.x # must use C4.x, not just x

当对象被声明的时候,其中的一些属性已经被隐式声明了。

__name__:类的名称

__base__:tuple对象,放置对象的所有基类

__dict__:dict对象,放置对象的所有属性

例如:对象C内部有属性S,那么C.S=x 等价于C._ _dict_ _['S']=x

1.1.3.2 对象内部的函数

对象内部的函数写法与普通的函数写法差不多,不过函数的第一个参数要写为self,如:

class C5:

def hello(self):

print "Hello"

1.1.3.3 私有变量

私有变量的声明,只需在变量名前面加两个下划线,如类C的内部有私有变量user,应声明为:__user。

事实上,当python编译的时候,会把__user改为_C__user(即_ClassName__VariableName的格式)。

无论是否在对象内部,以一个下划线开头的变量,都被看作私有变量。

1.1.4 实例

回顾一下前面的“经典对象的一些特征”中的第一点:“你可以象调用函数一样的来调用一个对象”。创建实例的时候,就是如此创建:

anInstance = C5( )

1.1.4.1 _ _init_ _

如果一个对象的内部,有或继承有_ _init_ _方法,那么当这个对象被调用(用java上的词可以叫实例化)时,_ _init_ _方法会自动地被调用。

_ _init_ _方法不能有返回值,如果一定需要跳出或返回,也只能返回None。

例如:

class C4:

def __init__(self):

return 'sss'

a = C4();

python会报错:

Traceback (most recent call last):

File "<pyshell#26>", line 1, in -toplevel-

a = C4();

TypeError: __init__() should return None

_ _init_ _方法的主要目的,是为了在创建对象实例的时候,对对象的属性赋值。这么做可以增加程序的可读性。如果对象内部没有_ _init_ _,那么你调用对象的时候就不能带上任何的参数。

1.1.4.2 实例中的属性

用点(.)来访问实例中的属性。

即使一个对象已经被实例化,仍可以个实例增加任意的属性,并对其赋值。

class C7: pass

z = C7( )

z.x = 23

实例被创建以后,该实例会被自动加上两个属性:

_ _class_ _:实例所属的对象

_ _dict_ _:实例的所有属性(实例自身的属性和其所属对象的属性)

如:

class C6:

def _ _init_ _(self,n):

self.x = n

a = C6(234)

a.y=213213

a.__dict__

#执行结果:{'y': 213213, 'x': 234}

1.1.4.3 工厂函数

遥想一下,设计模式中被用得最多得工厂模式(Factory),它被用于创建对象的实例。在python当中,最直接的用来实现工厂模式的方式,似乎是用_ _init_ _来返回不同的实例,但是,unfortunately,_ _init_ _最多也只能返回None。所以要实现工厂模式,最佳的方式就是专门写一个函数,用来返回不同的实例,这类函数,可以称之为工厂函数(Factory Function)。

如下例,appropriateCase就是一个工厂函数。

class SpecialCase:

def amethod(self): print "special"

class NormalCase:

def amethod(self): print "normal"

def appropriateCase(isnormal=1):

if isnormal: return NormalCase( )

else: return SpecialCase( )

aninstance = appropriateCase(isnormal=0)

aninstance.amethod( )

1.1.5 属性引用

假设x是对象C的实例,当引用x.name的时候,是如何来查找它的值呢?用最简单的话来概括,就是,由小到大由近到远,依次查找name的值。

再说得具体一些,是按下面的方式查找:

l 若x.name是x._ _dict_ _,中的key,那么返回x._ _dict_ _['name'] (查找自身)

l 否则,查找C._ _dict_ _中的key,是则返回C._ _dict_ _['name'] (查找所属对象)

l 否则,查找C的基类,在C._ _bases_ _中继续按上面的两步查找(查找所属对象的基类)

l 否则,抛出异常:AttributeError

1.1.6 方法的绑定与非绑定(Bound and Unbound)

上面讲了属性的引用,方法的绑定与非绑定实际上涉及到的是方法引用的问题。方法实际上使用函数来实现。当方法被引用时,并非直接返回其对应的函数,而是将这个函数,载入到了bound或者unbound方法上。

bound和unbound的区别在于:bound将特定的函数,与特定的实例相关联;而unbound则相反。

若没有同名属性,直接用函数名(函数名后不带括号),可以观察到其绑定状态。

假设有对象C和实例x:

class C:

a = 1

def g(self): print "method g in class C"

x = C()

print x.g

#执行结果:<bound method C.g of <__main__.C instance at 0x00BA2F58>>

print C.g

#执行结果:<unbound method C.g>

上面的执行结果表明:x.g被绑定到了C.g()函数上,所以执行x.g()会有结果返回;而C.g没有被绑定,所以执行C.g()没有结果。

1.1.6.1 细说非绑定

若处于非绑定状态,当一个函数被引用的时候,实际返回的是unbound方法,该方法内部载有该函数。Unbound方法有三个只读属性

im_class:被引用函数所在的对象

im_func:被引用的函数

im_self:总是为None

非绑定的方法也可以被调用,需要把im_class对象的实例名做为第一个参数,那么就会返回im_func的函数了。

例如上面的C.g()没有结果,但可以执行C.g(x),x为C的实例,就可以得到C.g()函数的正确执行结果了。

1.1.6.2 细说绑定

当执行x.g()时,返回的是bound 方法。bound方法和unbound方法类似,也有三个只读属性:im_class,im_func,im_self,但不同之处在于:im_self的值为x。

1.1.7 继承与重载

从前面说到的“属性引用”的查找方法,不难看出python继承的实现方式。若x为C的实例,当调用x.g()的时候,python先看x._ _dict_ _中有没有g,没有就查找C._ _dict_ _,若再没有就查找C._ _base_ _有没有g。C._ _base_ _中放置了C的基类,就实现了对象的继承。用这样的机制,也同样实现了重载。

1.1.7.1 超类代理

在子类中,有可能要用到超类的属性,那么就要使用到超类代理机制,实际上是用unbound方式调用超类的函数。例如:

class Base:

def greet(self, name): print "Welcome ", name

class Sub(Base):

def greet(self, name):

print "Well Met and",

Base.greet(self, name)

x = Sub( )

x.greet('Alex')

超类代理常用于_ _init_ _方法中,因为在python中,子类的_ _init_ _方法中并不会自动地调用其超类中的_ _init_ _方法,所以需要利用这种超类代理机制手动调用一下。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有