python基础之类的继承与派生、组合、接口与归一化设计、抽象类、子类中调用父类方法
2017-04-19 15:18
866 查看
一、什么是继承
继承是一种创建新的类的方式,新建的类可以继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类。派生:子类继承了父类的属性,然后衍生出自己新的属性,如果子类衍生出的新的属性与父类的某个属性名字相同,那么再调用子类的这个属性,就以子类自己这里的为准了。
python中类的继承分为:单继承和多继承
class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
查看继承:
print(SubClass1.__bases__) print(SubClass2.__bases__) #输出结果: # (<class '__main__.ParentClass1'>,) # (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
提示:如果没有指定基类,Python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。
print(ParentClass1.__bases__) print(ParentClass2.__bases__) #输出结果: # (<class 'object'>,) # (<class 'object'>,)
二 继承与抽象(先抽象再继承)
抽象即抽取类似或者说比较像的部分。抽象分成两个层次:
1、将奥巴马和梅西这俩对象比较像的部分抽取成类
2、将人,猪,狗这三个类比较像的部分抽取成父类
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
class A: def test(self): print('from A') pass class B(A): def test(self): print('from B') pass class C(A): def test(self): print('from C') pass class D(B): def test(self): print('from D') pass class E(C): def test(self): print('from E') pass class F(D,E): def test(self): print('from F') pass f1=F() f1.test() #深度优先: F->D->B->A->E->C
经典类的继承顺序
(2)继承原理(Python如何实现的继承)
python到底是如何实现继承的,对于你定义的每一个类,Python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
>>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
为了实现继承,Python会再MRO列表上从左到右开始查找基类,知道找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去探究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三天准则:
子类会先于父类被检查
多个父类会根据它们在列表中的顺序被检查
如果对下一个类存在两个合法的选择,选择第一个父类
八 子类中调用父类方法
子类继承了父类的方法,然后想进行修改,注意了是基于原有的基础上修改,那么就需要在子类中调用父类的方法方法一:父类名.父类方法()
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): Vehicle.__init__(self,name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) Vehicle.run(self) line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
方法二:super()
super在python2中的用法:
super(自己的类,self).父类的函数名字,super只能用于新式类
1、
#coding:utf-8 #super在python2中的用法: # 1:super(自己的类,self).父类的函数名字 # 2:super只能用于新式类 class People(object): def __init__(self,name,sex,age): self.name=name self.age=age self.sex=sex def walk(self): print('%s is walking' %self.name) class Chinese(People): country='China' def __init__(self,name,sex,age,language='Chinese'): # self.name=name # self.sex=sex # self.age=age # People.__init__(self,name,sex,age) super(Chinese,self).__init__(name,sex,age) self.language=language c=Chinese('egon','male',18) print c.name,c.age,c.sex,c.language #在python3中 class People: def __init__(self,name,sex,age): self.name=name self.age=age self.sex=sex def walk(self): print('%s is walking' %self.name) class Chinese(People): country='China' def __init__(self,name,sex,age,language='Chinese'): # self.name=name # self.sex=sex # self.age=age # People.__init__(self,name,sex,age) super(Chinese,self).__init__(name,sex,age) #python3中不用super()中传参, self.language=language def walk(self,x): super().walk() print('子类的x',x) c=Chinese('egon','male',18) # print(c.name,c.age,c.sex,c.language) c.walk(123)
2、
class Vehicle: #定义交通工具类 Country='China' def __init__(self,name,speed,load,power): self.name=name self.speed=speed self.load=load self.power=power def run(self): print('开动啦...') class Subway(Vehicle): #地铁 def __init__(self,name,speed,load,power,line): #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self) super().__init__(name,speed,load,power) self.line=line def run(self): print('地铁%s号线欢迎您' %self.line) super(Subway,self).run() class Mobike(Vehicle):#摩拜单车 pass line13=Subway('中国地铁','180m/s','1000人/箱','电',13) line13.run()
不用super引发的惨案:
#每个类中都继承了且重写了父类的方法 class A: def __init__(self): print('A的构造方法') class B(A): def __init__(self): print('B的构造方法') A.__init__(self) class C(A): def __init__(self): print('C的构造方法') A.__init__(self) class D(B,C): def __init__(self): print('D的构造方法') B.__init__(self) C.__init__(self) pass f1=D() print(D.__mro__) #python2中没有这个属性
当你使用super()函数时,python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整MRO列表,每个方法也只会被调用一次。
注:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表。
#每个类中都继承了且重写了父类的方法 class A: def __init__(self): print('A的构造方法') class B(A): def __init__(self): print('B的构造方法') super(B,self).__init__() class C(A): def __init__(self): print('C的构造方法') super(C,self).__init__() class D(B,C): def __init__(self): print('D的构造方法') super(D,self).__init__() f1=D() print(D.__mro__) #python2中没有这个属性
参考链接:http://www.cnblogs.com/linhaifeng/articles/6182264.html
相关文章推荐
- python基础----继承与派生、组合、接口与归一化设计、抽象类、子类中调用父类方法
- Python基础-接口与归一化设计、抽象类、继承顺序、子类调用父类,多态与多态性
- Python基础-接口与归一化设计、抽象类、继承顺序、子类调用父类,多态与多态性
- Python开发基础-Day20继承实现原理、子类调用父类的方法、封装
- python基础之继承派生、组合、接口和抽象类
- Python开发基础-Day18继承派生、组合、接口和抽象类
- python基础之继承实现原理、子类调用父类的方法、封装
- php基础 继承_子类中如何调用父类的变量和方法
- 2018/01/08JAVA 基础 / 接口与继承:[Q]:若父类Hero提供了一个有参的构造方法,但是没有提供无参的构造方法。子类应该怎么处理?
- C#中通过类来继承两个接口,父类实例化接口中的方法,子类继承父类,调用方法
- Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类
- C#中通过类来继承两个接口,父类实例化接口中的方法,子类继承父类,调用方法
- Java基础——继承+子父类相关特点+Final关键字+抽象类+模板方法设计模式+接口
- 2018/01/08JAVA 基础 / 接口与继承:调用父类/子类的类方法、对象方法,访问父类的类属性、对象属性的方式汇总
- Python 继承、派生、组合、接口、抽象类
- 继承父类,调用父类中的方法 分类: python 小练习 python基础学习 2014-01-10 17:54 325人阅读 评论(0) 收藏
- Python3基础 super层层调用父类的__init__方法 子类的__init__覆盖了父类的__init__的解决方法
- Python基础(16)_面向对象程序设计(类、继承、派生、组合、接口)
- 2018/01/08JAVA 基础 / 接口与继承/Java关键词:变量引用 super 调用父类对象方法/构造方法【或者访问父类对象属性】的方式归纳
- 2018/01/07JAVA 基础 / 接口与继承:重写【子类继承并覆盖父类的对象方法】、隐藏【子类继承并覆盖父类的类方法】与实现类实现接口方法の区别