python中如何进行类的派生与继承_Python入门之面向对象之类继承与派生

本文详细介绍了Python中的类继承与派生,包括继承的定义、为何使用继承、如何使用继承,以及继承的实现原理。通过示例代码展示了如何创建子类、调用父类方法,并探讨了Python2和Python3中类的区别。同时,文章还讨论了抽象类的概念,以及处理多重继承的建议。
摘要由CSDN通过智能技术生成

本章内容

一、继承

二、抽象类

三、继承的实现原理

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

一、继承

1. 继承的定义

继承是一种新建类的方式,新建的类被称为子类,子类会继承父类的属性。

在Python中支持,一个子类(派生类——可以继承一个或者多个父类(基类或者超类)

2. 为什么要用继承

继承可以有效减少代码冗余

3. 如何使用继承

继承代码示例

#继承示例

classFather1:pass

classFather2:pass

class Son1(Father1): #Son1继承Father1

pass

class Son2(Father1,Father2): #Son2同时继承Father1 & Father2

pass

print(Son1.__bases__)print(Son2.__bases__)print(Father1.__bases__)print(Father2.__bases__)

以上代码的结果如下:

(,) #Son1继承Father1

(, ) #Son2继承Father1,Father2

(,)   #Python3中有默认父类object

(,)   #Python3中有默认父类object

#在python3新建的类,默认都有一个父类(object)

#在python2中,默认是没有父类,可以添加(object)为父类

需要注意Python2和Python3中关于类的分类是不一样的:

#Python2中的类:# #1.经典类#指的是没有继承默认父类object的类,以及没有继承object类的子类#

#2.新式类#值得是继承默认父类object以及object类子类的类#

#

#Python3中的类:# #统一都是新式类

4. 建立继承关系

继承是类与类之间的关系,需要寻找这种关系,先进行抽象,然后建立继承

子类所共有的特征,由父类进行统一配置管理

classSchoolPeople:

school= 'SH high school'

def __init__(self,name,age,gender):

self.name=name

self.age=age

self.gender=genderdeftell_info(self):print('School:Name is %s, Age is %s, Gender is %s' %(name,age,gender))class SchoolStudent(SchoolPeople): #继承SchoolPeople

deflearn(self):print('%s is learning' %name)deftell_info(self):print('I'm student %s, Age is %s, Gender is %s '%(name,age,gender))

class SchoolTeacher(schoolPeople): #继承SchoolPeople

defteach(self):print('%s is teaching' %name)deftell_info(self):print('I'm teacher %s, Age is %s, Gender is %s '%(name,age,gender))

student1= SchoolStudent('Bob','22','Male')

teacher1= SchoolTeacher('Ajax','33','Female')print(student1.__dict__)print(student1.school)print(teacher1.__dict__)#子类已经自己定义tell_info()函数,显示格式将按照子类的格式显示,不需要按照父类的格式

student1.tell_info()

teacher1.tell_info()

请仔细查看如下代码:

classFoo:defF1(self):print('Foo.F1')defF2(self):print('Foo.F2')

self.F1()class Bar(Foo): #继承Foo

def F1(self): #子类中同时也有与父类同名的方法F1

print('Bar.F1')

obj=Bar()

obj.F2()#obj先到父类Foo中找到F2方法运行#运行到self.F1()的时候会调用子类Bar自己的F1()方法,而不在调用父类的F1()方法

以上显示的结果为:

Foo.F2

Bar.F1

5. 子类派生出新的方法中重用父类的功能

派生,是指子类定义自己新的属性,如果与父类同名,以子类自己的为准

a. 调用父类方法,指名道姓的使用,请看如下代码

classSchoolPeople:

school= 'oldboy'

def __init__(self, name, age, sex):

self.name=name

self.age=age

self.sex=sexdeftell_info(self):print("""===========个人信息==========

姓名:%s

年龄:%s

性别:%s""" %(self.name,self.age,self.sex))class SchoolTeacher(SchoolPeople): #继承SchoolPeople

def __init__(self, name, age, sex, level, salary):#self.name = name

#self.age = age

#self.sex = sex

SchoolPeople.__init__(self,name, age, sex) #点名指向SchoolPeople

self.level=level

self.salary=salarydeftell_info(self):

SchoolPeople.tell_info(self)#点名指向SchoolPeople

print("""等级:%s

薪资:%s""" %(self.level,self.salary))

tea1= SchoolTeacher('Bob', 18, 'male', 9, 50k)#print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary)

tea1.tell_info()

b. 调用父类方法,使用super()方法

注意区分Python2和Python3中的super()的格式

这种方法只能调用父类的方法

classSchoolPeople:

school= 'oldboy'

def __init__(self, name, age, sex):

self.name=name

self.age=age

self.sex=sexdeftell_info(self):print("""===========个人信息==========

姓名:%s

年龄:%s

性别:%s""" %(self.name,self.age,self.sex))class SchoolTeacher(SchoolPeople): #继承SchoolPeople

def __init__(self, name, age, sex, level, salary):#self.name = name

#self.age = age

#self.sex = sex

super().__init__(self,name, age, sex) #使用super()指向父类,Python3的格式

#super(SchoolPeople,self).__init__(self,name, age, sex) Python2的格式

self.level =level

self.salary=salarydeftell_info(self):

super().tell_info(self)#使用super()指向父类,Python3的格式

#super(SchoolPeople,self).tell_info(self) Python2的格式

print("""等级:%s

薪资:%s""" %(self.level,self.salary))

tea1= SchoolTeacher('Bob', 18, 'male', 9, 50k)#print(tea1.name, tea1.age, tea1.sex, tea1.level, tea1.salary)

tea1.tell_info()

二、抽象类

主要使用abc模块,实现归一化,父类有的方法,子类必须有。

需要在父类的方法头部加上@abc.abstractclassmethod

class File(metaclass=abc.ABCMeta):

@abc.abstractmethoddef read(self): #必须要定义下面的方法,如果没有就不让实例化

pass@abc.abstractmethoddefwrite(self):pass

classSata(File):defread(self):pass

defwrite(self):pass

defasb(self):print('adsf')

Fil=Sata()

Fil.asb()print(Sata.mro())

三、继承的实现原理

1、继承顺序:

经典类:当类是经典类时,多继承情况下,在要查找属性不存在时,会按照深度优先的方式查找下去

新式类:当类是新式类时,多继承情况下,在要查询属性不存在时,会按照广度优先的方式查找下去

2、方法解析顺序(Method Resolution Order, MRO)

在多重继承中存在不相关的祖先类实现同名方法引起的冲突问题,这种问题称作“菱形问题”。

Python依靠特定的顺序遍历继承图,这个顺序叫做方法解析顺序。

如图,左图是类的UML图,右图中的虚线箭头是方法解析顺序:

3、使用属性来查看继承的顺序:

print(类名.mro())

classA(object):#def test(self):

#print('from A')

pass

classB(A):#def test(self):

#print('from B')

pass

classC(A):#def test(self):

#print('from C')

pass

classD(B):#def test(self):

#print('from D')

pass

classE(C):#def test(self):

#print('from E')

pass

classF(D,E):#def test(self):

#print('from F')

passf1=F()print(F.mro())

4. 处理多重继承的建议

(1)把接口继承和实现继承区分开;

继承接口:创建子类型,是框架的支柱;

继承实现:通过重用避免代码重复,通常可以换用组合和委托模式。

(2)使用抽象基类显式表示接口;

(3)通过混入重用代码;

混入类为多个不相关的子类提供方法实现,便于重用,但不会实例化。并且具体类不能只继承混入类。

(4)在名称中明确指明混入;

Python中没有把类声明为混入的正规方式,Luciano推荐在名称中加入Mixin后缀。如Tkinter中的XView应变成XViewMixin。

(5)抽象基类可以作为混入,反过来则不成立;

抽象基类与混入的异同:

抽象基类会定义类型,混入做不到;

抽象基类可以作为其他类的唯一基类,混入做不到;

抽象基类实现的具体方法只能与抽象基类及其超类中的方法协作,混入没有这个局限。

(6)不要子类化多个具体类;

具体类可以没有,或者至多一个具体超类。

例如,Class Dish(China,Japan,Tofu)中,如果Tofu是具体类,那么China和Japan必须是抽象基类或混入。

(7)为用户提供聚合类;

聚合类是指一个类的结构主要继承自混入,自身没有添加结构或行为。Tkinter采纳了此条建议。

(8)优先使用对象组合,而不是类继承。

优先使用组合可以令设计更灵活。

组合和委托可以代替混入,但不能取代接口继承去定义类型层次结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值