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
这样很明显。很给力!!
用法很有劲。分享给大家了,在编写程序的时候有帮助!!!!