http://www.cnblogs.com/mingaixin/archive/2013/01/31/2887043.html
python和C++一样,支持多继承。概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。
对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现:
经典类:
-
#! /usr/bin/python
-
# -*- coding:utf-8 -*-
-
-
class P1():
-
def foo(self):
-
print 'p1-foo'
-
-
class P2():
-
def foo(self):
-
print 'p2-foo'
-
def bar(self):
-
print 'p2-bar'
-
-
class C1(P1,P2):
-
pass
-
-
class C2(P1,P2):
-
def bar(self):
-
print 'C2-bar'
-
-
class D(C1,C2):
-
pass
-
-
-
if __name__ =='__main__':
-
d=D()
-
d.foo()
-
d.bar()
执行的结果:
p1-foo
p2-bar
将代码实例,画了一个图,方便理解:
从上面经典类的输出结果来看,
实例d调用foo()时,搜索顺序是 D => C1 => P1,
实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2
总结:经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,如果没有则继续向上查找,直到在P1中找到该方法,查找结束。
新式类:
-
#! /usr/bin/python
-
# -*- coding:utf-8 -*-
-
-
class P1(object):
-
def foo(self):
-
print 'p1-foo'
-
-
class P2(object):
-
def foo(self):
-
print 'p2-foo'
-
def bar(self):
-
print 'p2-bar'
-
-
class C1(P1,P2):
-
pass
-
-
class C2(P1,P2):
-
def bar(self):
-
print 'C2-bar'
-
-
class D(C1,C2):
-
pass
-
-
-
if __name__ =='__main__':
-
print D.__mro__ #只有新式类有__mro__属性,告诉查找顺序是怎样的
-
d=D()
-
d.foo()
-
d.bar()
执行的结果:
(, , , , , )
p1-foo
C2-bar
从上面新式类的输出结果来看,
实例d调用foo()时,搜索顺序是 D => C1 => C2 => P1
实例d调用bar()时,搜索顺序是 D => C1 => C2
总结:新式类的搜索方式是采用“广度优先”的方式去查找属性。(D->C1->C2->P1->P2)
----------------------------------------------------------------------------------
说明: __new__()是在新式类中新出现的方法, 在实例化开始之后,在调用__init__()方法之前,Python首先调用__new__()方法.
说明:__init__方法在类的对象被建立时,马上运行。该方法用来对对象进行初始化。
说明:__del__方法是在程序退出时调用的。
如果其基类也具有__init__(), 必须显式地在__init__()调用它, 以保证能够适当地初始化它的基类部分;例如:
"BaseClass.__init__(self, [args...])"作为构造器的特殊情况, 它没有值被返回, 如果返回某个值,
会在运行时抛出异常TypeError.
----------------------------------------------------------------------------------
python中的继承 http://blog.chinaunix.net/uid-22920230-id-3070742.html
继承是面向对象的重要特征之一,继承是两个类或者多个类之间的父子关系,子进程继承了父进程的所有公有实例变量和方法。继承实现了代码的重用。重用已经存在的数据和行为,减少代码的重新编写,python在类名后用一对圆括号表示继承关系,
括号中的类表示父类,如果父类定义了__init__方法,则子类必须显示地调用父类的__init__方法,如果子类需要扩展父类的行为,可以添加
__init__方法的参数。
下面演示继承的实现
class Fruit:
def __init__(self, color):
self.color = color
print "fruit's color: %s" %self.color
def grow(self):
print "grow..."
class Apple(Fruit): #继承了父类
def __init__(self, color): #显示调用父类的__init__方法
Fruit.__init__(self, color)
print "apple's color: %s" % self.color
class Banana(Fruit): #继承了父类
def __init__(self, color): #显示调用父类的__init__方法
Fruit.__init__(self, color)
print "banana's color:%s" %s self.color
def grow(self): #覆盖了父类的grow方法
print "banana grow..."
if __name__ == "__main__":
apple = Apple("red")
apple.grow()
banana = Banana("yellow")
banana.grow()
输出结果:
fruit‘s color : red
apple's color : red
grow...
fruit's color : yellow
banana's color : yellow
banana grow...
抽象类的模拟
抽象类是对一类事物特征和行为的抽象,抽象类由抽象方法组成,python2.5没有提供抽象类的语法,抽象类的特征是不能被实例化,但是可以通过
python的NotImplementedError类来模拟抽象类,NotImplementedError类继承自python运行时错误类
RuntimeError。当对抽象类进行实例化时,将抛出异常。
模拟抽象类的实现
def abstract(): #定义了全局函数
raise NotImplimentedError(“abstract”):
class Fruit:
def __init__(self):
if self.__class__ is Fruit: #如果实例化的类是Fruit,则抛出异常
abstract()
print "Fruit..."
class Apple(Fruit):
def __init__(self):
Fruit.__init__(self)
print "Apple..."
if __name__ == "__main__":
apple = Apple() #输出: Fruit Apple
同样python也没有提供对接口的支持。接口是特殊的抽象类,接口没有数据成员,而是一组未实现的方法的集合。
阅读(968) | 评论(0) | 转发(0) |