您的位置:首页 > 编程语言 > Python开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐