python面向对象开发(继承)

Python课堂实录-面向对象(继承)

视频地址:http://v.youku.com/v_show/id_XNDg3NjM3OTg0.html

面向对象:1.封装 2.继承 3.多态

python中关于父类子类的继承!


类之间的关系,类的继承,组合,依赖

1.类的关系
-----------当多个类被设计完成时,一般都会有类与类之间的相互关系;类之间的存在的继承、组合、依赖等关系;

---继承是面向对象的最重要的特性之一;
继承关系:继承是对两个类而言的父子关系。
----------子类继承了父类的所有共有属性和方法;
----------继承实现了代码的重用


[使用继承]
继承可以重用已经存在的数据和行为,减少代码的重复编写。python在类名后使用一对括号来表示继承的关系,括号中的类即为父类。

格式:
class MyClass(ParentClass):
注意:
如果父类中定义了__init__方法,子类必须显示调用父类的__init__ 方法
( "BaseClass.__init__(self,[args...])" )。                    # 这个在本文的最后有描述,可看!!

                                # 就是让 子类 不管别的继承的了,可以自由选择一个 父类的 构造方法 做 自己的 构造方法(__init__)!!
如果子类需要扩展父类的行为,可以添加__init__方法的参数

子类继承父类 所有的属性和方法!(包括私有属性,私有方法,但是调用的时候得用 test._Parent__var2 而不是 test._Child__var2 )

所有的公有方法,都直接让子类继承了。父类Parent有 var1, 子类中没有var1. 但是 子类创建的对象test 有 test.var1 !

子类继承父类的所有公有属性-----是同名的!!!

子类继承父类的所有公有方法-----是同名的!!!

 

子类继承父类所有方法
[多重继承]
python 支持多重集成,即一个类可以继承多个父类;
多重继承的语法格式:
class_name(parent_class1, parent_class2,...)

---注意:
——————————当父类中出现多个自定义的__init__方法时,多重继承只执行第一个类的__init__方法,其他不执行。

----------如果子类里面有自己 的初始化方法的话,__init__(): 先按照子类中自己的初始化方法执行,而后再考虑后面类中的方法。

--------例子如下:

 1 #!/usr/bin/env python
 2 #coding:utf8
 3 
 4 class Parent():
 5     var1 = "这是父类的一个公有属性"
 6     __var2 = "这是父类的一个私有属性"
 7     def fun(self):
 8         print "我是父类的一个公有方法"
 9 
10     def __fun2(self):
11         print "我是父类的一个私有方法"
12 
13     @classmethod
14     def parentClassMethod(self):
15         return "我是父类的一个类方法"
16 
17     @staticmethod
18     def parentStaticMethod():           # 静态方法不需要加self(已全加载到内存)
19         return "我是父类的一个静态方法"
20 
21 class Child(Parent):
22     def funC(self):
23         print "我是子类的一个公有方法"
24         print Parent.var1               # 通过这种方式调用父类公有属性
25 #        print Parent.__var2            # 出错!不能调用父类的私有属性
26 
27 test = Child()
28 test.funC()
29 test.fun()              # 子类继承了父类的所有公有属性和方法
30 test._Parent__fun2()    # 通过这种方法,直接调用父类中的私有类,比较变态!
31                         # 一般在测试中使用,间接证明了:
32                         # 子类完全继承了父类的公有方法,和私有方法
33 print test._Parent__var2        # 父类的一个私有属性
34 print Parent.parentStaticMethod
35 print Parent.parentClassMethod
36 # print test._Child__var2               # 出错,因为子类Child中没有__var2
37                                 # 如果非要调用不可,则用test._Parent__var2

输出结果为:

alex@universe ~/python/OOP $ python cls_parent.py
我是子类的一个公有方法
这是父类的一个公有属性
我是父类的一个公有方法
我是父类的一个私有方法
这是父类的一个私有属性
<function parentStaticMethod at 0x7fc2e4389668>
<bound method classobj.parentClassMethod of <class __main__.Parent at 0x7fc2e43710b8>>
alex@universe ~/python/OOP $ 

这说明,在类的继承中,子类可以直接继承父类的方法。(私有方法也可以通过隐藏在别的类中使用,或者是调试的时候用test._Parent__fun2() 来使用。这里后缀必须是Parent,不能是 test._Child__fun2()  !!! )

这里直接访问 test.var1 就是 类Child 的父类 Parent 的公有属性 var1。

反正要说明的一点是:

在 test = Child() 之后 创建一个新的对象之后,

test._Parent__fun2()

test._Parent__var2

都是可行的!!!说明,子类能继承父类所有的属性!!!

test._Child__fun2()

test._Child__var2  都是不可行的!!!!

类继承有个好处,就是类的重载省事了

类的重载!

让我们来看看一个实例!

 1 #!/usr/bin/env python
 2 #coding:utf8
 3 
 4 class Human():
 5     body = "有胳膊有腿"
 6     head = "会思考"
 7     nationality = "地球人"
 8     def say(self):
 9         print "会说话"
10 
11 class Chinese(Human):
12     pass
13 
14 class English(Human):
15     nationality = "英国人"
16     def say(self):
17         print "会说英语"
18 zhang = Chinese()
19 tom = English()
20 print "----未给张设定国籍前----"
21 print zhang.nationality
22 print "----给张设定国籍后----"
23 zhang.nationality = "中国人"
24 print zhang.nationality
25 zhang.say()
26 print "----看看tom这个英国人----"
27 print tom.nationality
28 tom.say()

运行显示的结果为:

alex@universe ~/python/OOP $ python cls_parent_chinese.py
----未给张设定国籍前----
地球人
----给张设定国籍后----
中国人
会说话
----看看tom这个英国人----
英国人
会说英语

这里我们看到,子类中,还可以重载一些父类中的属性。

上面的例子中,我们重载了 zhang 和 tom 的国籍。

但是我们并没有重载zhang 所说的 语言。所以他还是只会说话。而tom, 在class English(): 中,已经重新def say(): 这个方法了。

所以,tom 直接就是会说英语了。

子类的属性重载,有几种方式。

1. 是在class Child(Parent): 中,重新定义nationality = "中国人" ,重新定义,这里,变量名 nationality 与 父类里的变量名是一样的。

2. 是在对象实例化以后修改。 zhang.nationality = "中国人" , 这样的方式,也能起到修改国籍的作用。

---针对不同需求,我们可以采用不同的方法。1,2 还是有小区别的,读者自行比较。

 

类的多重继承

类Chinese 同时继承了Human,继承了Animal

如下:

 1 #!/usr/bin/env python
 2 #coding:utf8
 3 
 4 class Human():
 5     name = "人类"
 6     def say(self):
 7         print "会说话"
 8 
 9 class Animal():
10     name = "动物"
11 
12 class Chinese(Animal, Human):
13     #name = "中国人"
14     def say(self):
15         print "会说中国话"
16 zhang = Chinese()
17 print zhang.name

输出结果为:

alex@universe ~/python/OOP $ python cls_parent_multiply.py
动物

原因是,先继承谁,谁的类属性就优先级就越高。这个例子里面是父类Animal排在前面,故输出的是“动物”!!

子类所继承的父类中,相同变量只加载一次!取最靠前的父类那个加载!

如果,换过来成class Chinese(Human, Animal):

结果就是输出的是“人类”。

=========================================================================

子类 父类 祖类

这个有意思,哈哈,继承两代!

 1 #!/usr/bin/env python
 2 #coding:utf8
 3 class Animal():                 # 祖类必须排在父类上面!
 4     name = "动物"               #                       遵守程序原理!!
 5 
 6     def __init__(self):
 7         self.name = "AAAAAAAAAAAAAAAA"
 8 
 9 
10 class Human(Animal):            # 父类继祖类
11     name = "人类"
12 
13     def __init__(self):
14         self.name = "HHHHHHHHHHHHHHHHH"
15 
16     def say(self):
17         print "会说话"
18 
19 class Chinese(Human):           # 子类继承父类
20     #name = "中国人"
21     def say(self):
22         print "会说中国话"
23 zhang = Chinese()
24 print zhang.name

运行的输出结果是:

alex@universe ~/python/OOP $ python cls_parent_multiply.py
HHHHHHHHHHHHHHHHH

解释:

因为类Human 继承了类Animal,而Human有构造方法__init__():,所以,不采用Animal中的>构造方法__init__(): 。 而,子类没有__init__(), 所以显示的是Human的构造方法__init__():

[子][父][祖] 有意思吧!

还有更有意思的!

 1 #!/usr/bin/env python
 2 #coding:utf8
 3 class Animal():                 # 祖类必须排在父类上面!
 4     name = "动物"               #                       遵守程序原理!!
 5 
 6     def __init__(self):
 7         self.name = "AAAAAAAAAAAAAAAA"
 8 
 9 
10 class Human(Animal):            # 父类继祖类
11     name = "人类"
12 
13     def __init__(self):
14         self.name = "HHHHHHHHHHHHHHHHH"
15 
16     def say(self):
17         print "会说话"
18 
19 class Chinese(Human):           # 子类继承父类
20     #name = "中国人"
21 
22     def __init__(self):
23         Animal.__init__(self)           # 在子类中的构造函数__init__()中加上祖类Animal额构造函数,Animal__init__(self):
24                                         # 目的是为了直接调用祖类的构造函数,其他继承的不管了!!!!
25 
26     def say(self):
27         print "会说中国话"
28 zhang = Chinese()
29 print zhang.name

这样可以让子类直接使用 祖类的构造函数 做 子类自己的构造函数。很有意思!!!!

输出结果是

alex@universe ~/python/OOP $ python cls_parent_multiply.py
AAAAAAAAAAAAAAAA

这样很明显。很给力!!

用法很有劲。分享给大家了,在编写程序的时候有帮助!!!!

 

posted @ 2013-03-26 02:52  spaceship9  阅读(443)  评论(0编辑  收藏  举报