Chinaunix首页 | 论坛 | 博客
  • 博客访问: 123905
  • 博文数量: 83
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-13 10:26
个人简介

- 毅力与勇气是事业的双飞翼; - 在尝试中成长,在失败中奋起。 - 概览 -> 细读 -> 概览 - 书不在多,在于精。

文章分类

全部博文(83)

文章存档

2016年(2)

2015年(6)

2014年(75)

我的朋友

分类: Python/Ruby

2014-07-21 20:54:07

http://www.cnblogs.com/mingaixin/archive/2013/01/31/2887043.html

python和C++一样,支持多继承。概念虽然容易,但是困难的工作是如果子类调用一个自身没有定义的属性,它是按照何种顺序去到父类寻找呢,尤其是众多父类中有多个都包含该同名属性。

对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现

经典类:

点击(此处)折叠或打开

  1. #! /usr/bin/python
  2. # -*- coding:utf-8 -*-

  3. class P1():
  4.     def foo(self):
  5.         print 'p1-foo'

  6. class P2():
  7.     def foo(self):
  8.         print 'p2-foo'
  9.     def bar(self):
  10.         print 'p2-bar'

  11. class C1(P1,P2):
  12.     pass

  13. class C2(P1,P2):
  14.     def bar(self):
  15.         print 'C2-bar'

  16. class D(C1,C2):
  17.     pass


  18. if __name__ =='__main__':
  19.     d=D()
  20.     d.foo()
  21.     d.bar()


执行的结果:

p1-foo
p2-bar

将代码实例,画了一个图,方便理解:

从上面经典类的输出结果来看,

实例d调用foo()时,搜索顺序是 D => C1 => P1

实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2

总结:经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,如果没有则继续向上查找,直到在P1中找到该方法,查找结束。

 

新式类:

点击(此处)折叠或打开

  1. #! /usr/bin/python
  2. # -*- coding:utf-8 -*-

  3. class P1(object):
  4.     def foo(self):
  5.         print 'p1-foo'
  6.         
  7. class P2(object):
  8.     def foo(self):
  9.         print 'p2-foo'
  10.     def bar(self):
  11.         print 'p2-bar'
  12.         
  13. class C1(P1,P2):
  14.     pass
  15.     
  16. class C2(P1,P2):
  17.     def bar(self):
  18.         print 'C2-bar'
  19.         
  20. class D(C1,C2):
  21.     pass
  22.     

  23. if __name__ =='__main__':
  24.     print D.__mro__ #只有新式类有__mro__属性,告诉查找顺序是怎样的
  25.     d=D()
  26.     d.foo()
  27.     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也没有提供对接口的支持。接口是特殊的抽象类,接口没有数据成员,而是一组未实现的方法的集合。


阅读(933) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~