比起在例如C++、JAVA中,OOP在Python中理解和使用起来更简单。作为一个动态类型编程语言,Python移除了很多的复杂和混乱语法,包括其他工具中的Clouds OOP。事实上,Python中的大部分OOP赘述都可以归结为这个表达式:
object.attribute
之前我们已经用过这个表达式访问模块的属性、调用对象的方法等,对于一个由class语句产生的对象来说这个表达式在Python内是以搜索开始的——它搜索一个对象的相关树,寻找属性首次出现的地方,到类加入进来之后,之后的处理就可以用以下自然语言表述:
首先在object内寻找第一个出现的attribute,然后在这个类之上的所有类中寻找,按照从底向上从左到右的顺序。
换句话说,取属性就是树搜索。术语inheritance也适用,因为树中低级的对象从更高级的对象继承属性。随着从底向上的不断推进,在某种意义上来说,树中的对象是所有在它父对象中定义的属性的联合体。
在Python中,我们在写代码的时候建立相关的对象树,每次我们使用object.attribute
表达式的时候,在运行时的确是从下到上的沿着树搜索属性。
类和实例
在这个表中,有一个包含五个带有变量标注的对象。所有对象都带有属性,等待被搜索。更精确的讲,这个树是一个三个类对象(C1,C2,C3)加两个实例对象的继承搜索树。不过注意Python中的对象模型,类和由类产生的实例是两个完全不同的对象类型:
类:
扮演一个实例工厂的角色,他们的属性提供行为——数据和函数——这会被所有他们产生的实例所继承。
实例:
在程序域内代表具体的items。他们的属性记录数据,并且这些数据随着不同的特定对象而不同。
依据搜索树,一个实例从它的类继承属性,而类从树中在它之上的所有类中继承属性。
树中类的细分
在表中,我们可以根据在树中的相对位置的不同更加细化的分类。我们通常把在树中位置高一点的类称作(C2,C3) superclasses
;位置低一点的类称作subclasses
。这些术语涉及到了在树中的相对位置和角色。superclasses
提供被所有subclasses
共享的行为(behavior),但是因为搜索是从底向上推进的,subclasses
可能会覆盖在superclasses
中定义的行为。
继承搜索举例
因为上面的话在OOP中软件定制化中是关键,让我们扩展一下这个概念。设想我们建立一个表中的树,然后:
I2.w
这个代码会引起继承,因为这是一个object.attribute
表达式,它开始了表中树的搜索——Python会在I2
和之上的类中搜索属性w
。确切的讲,他会以下面的顺序搜索相关的对象:
I2,C1,C2,C3
然后会在第一个找到w
的地方停下(或者没找到的话抛出错误)。在这个例子中,直到搜索到C3
时才会找到w
,因为只有C3
中才有w
,用OOP术语讲,I2
从C3
继承属性w
。
这两个实例从他们的类中继承了4个属性:w,x,y和z。其他的属性引用在树中会沿着不同的路径寻找,例如:
- I1.x 和 I2x都是在C1中找到x并停止应为C1比C2 更低
- I1.y和I2.y都在C1中找到y因为只有C1有y
- I1.z和I2.z都在C2中找到z因为C2比C3更靠左
- I2.name 直接在I2中找到name,完全不需要网上寻找
仔细品味上面的例子会理解在Python中继承搜索是如何运作的。
重定义
值得注意的是,C1在树中更低级的地方重定义了属性x,取代了C2之上的版本。这样的重定义正是OOP中软件定制化的核心——重定义取代属性,C1很巧妙的定制化了从superclasses继承的东西。