面向对象——继承派生组合以及接口
Posted 申不二
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象——继承派生组合以及接口相关的知识,希望对你有一定的参考价值。
1.1 什么是继承
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
Python中类的继承分为:单继承和多继承
class People: # 定义父类 def __init__(self,name,age): self.name=name self.age=age def walk(self): print(\'%s is walking\' %self) class Teacher(People): # 单继承,基类是People,派生类是Teacher pass class Student(People): # 单继承,基类是People,派生类是Student pass t=Teacher(\'egon\',18) print(t.name,t.age) print(t.__dict__) t.walk()
需要注意圆括号中基类的顺序,若是基类中有相同的方法名,而在子类使用时为指定,Python从左至右搜索即方法在子类中未找到时,从左到右查找基类中是否包含方法。
如果没有指定基类,Python的类会默认继承object类,object是所有Python类的基类,它提供了一些常见方法如(__str__)的实现
BaseClassName(示例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
class DerivedClassName(modname.BaseClassName):
单继承实例:
#类定义 class people: #定义基本属性 name = \'\' age = 0 #定义私有属性,私有属性在类外部无法直接进行访问 __weight = 0 #定义构造方法 def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" %(self.name,self.age)) #单继承示例 class student(people): grade = \'\' def __init__(self,n,a,w,g): #调用父类的
二、多继承
class People: # 定义父类 pass class Animal: # 定义父类 pass class Student(People,Animal): # 定义子类 pass print(Student.__bases__) print(People.__bases__) print(Animal.__bases__)
在Python3中,所有类默认继承object
但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在Python3中所有的类都是新式类)
没有继承object类的子类成为经典类(在Python2中,没有继承object的类,以及它的子类,都是经典类)
继承的好处:
解决代码重用的问题,减少代码冗余
继承是一种什么‘是’什么的关系 # 比如:人是动物
class People: # 定义父类 # 定义构造方法 def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def walk(self): print(\'%s is walking\' %self.name) def foo(self): print(\'from father %s\' %self.name) class Teacher(People): # 定义派生(子类) school=\'oldboy\' # 定义基本属性 def __init__(self,name,age,sex,level,salary): # 定义构造方法 People.__init__(self,name,age,sex) self.level=level self.salary=salary def teach(self): print(\'% is teaching\' %self.name) def foo(self): People.foo(self) print(\'from teacher\') class Student(People): # 定义派生(子类) def __init__(self,name,age,sex,group): # 定义构造方法 People.__init__(self,name,age,sex) # 调用父类的构函 self.group=group def study(self): print(\'% is studying %self.name\') t=Teacher(\'egon\',18,\'male\',10,10000) # 实例化对象 s=Student(\'wocao\',22,\'male\',12) # 实例化对象 print(t.__dict__) print(s.__dict__) t.foo()
class Date: def __init__(self,year,mon,day): self.year=year self.mon=mon self.day=day def tell_brith(self): print(\'出生于<%s>年 <%s>月 <%s>日\' %(self.year,self.mon,self.day)) class Teacher: def __init__(self,name,age,year,mon,day): self.name=name self.age=age self.brith=Date(year,mon,day) def teach(self): print(\'%s is teaching\' %self.name) class Stdent: def __init__(self,name,age,year,mon,day): self.name=name self.age=age self.brith=Date(year,mon,day) def study(self): print(\'%s is studying\' %self.name) t=Teacher(\'egon\',18,1999,1,8) print(t.name,t.age) print(t.brith) print(t.brith.year) print(t.brith.mon) print(t.brith.day) t.brith.tell_brith()
通过继承建立了派生类与基类之间的关系,它是一种是的关系,比如白马是马,人是动物。
当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师
>>> class Teacher: ... def __init__(self,name,gender): ... self.name=name ... self.gender=gender ... def teach(self): ... print(\'teaching\') ... >>> >>> class Professor(Teacher): ... pass ... >>> p1=Professor(\'egon\',\'male\') >>> p1.teach() teaching
class BirthDate: def __init__(self,year,month,day): self.year=year self.month=month self.day=day class Couse: def __init__(self,name,price,period): self.name=name self.price=price self.period=period class Teacher: def __init__(self,name,gender): self.name=name self.gender=gender def teach(self): print(\'teaching\') class Professor(Teacher): def __init__(self,name,gender,birth,course): Teacher.__init__(self,name,gender) self.birth=birth self.course=course p1=Professor(\'egon\',\'male\', BirthDate(\'1995\',\'1\',\'27\'), Couse(\'python\',\'28000\',\'4 months\')) print(p1.birth.year,p1.birth.month,p1.birth.day) print(p1.course.name,p1.course.price,p1.course.period) \'\'\' 运行结果: 1 27 python 28000 4 months \'\'\'
class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。 def read(self): #定接口函数read pass def write(self): #定义接口函数write pass class Txt(Interface): #文本,具体实现read和write def read(self): print(\'文本数据的读取方法\') def write(self): print(\'文本数据的读取方法\') class Sata(Interface): #磁盘,具体实现read和write def read(self): print(\'硬盘数据的读取方法\') def write(self): print(\'硬盘数据的读取方法\') class Process(Interface): def read(self): print(\'进程数据的读取方法\') def write(self): print(\'进程数据的读取方法\')
# 父类要限制 # 1 子类必须要有父类的方法 # 2 子类实现的方法必须跟父类的方法的名字一样 import abc # 利用abc模块实现抽象类 class File(metaclass=abc.ABCMeta): @abc.abstractmethod # 定义抽象类方法,无需实现功能 def read(self): ‘子类必须定义读功能’ pass @abc.abstractmethod def writh(self): ‘子类必须定义写功能’ pass class Txt(File): # 子类继承抽象类,但是必须定义read和write方法 def read(self): # read方法,如果子类没有定义抽象方法,则报错 pass def writh(self): # write方法,和上面一样 pass t=Txt()
class A(object): def test(self): print(\'from A\') class B(A): def test(self): print(\'from B\') class C(A): def test(self): print(\'from C\') class D(B): def test(self): print(\'from D\') class E(C): def test(self): print(\'from E\') class F(D,E): # def test(self): # print(\'from F\') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类 继承顺序
>>> F.mro() #等同于F.__mro__ [<class \'__main__.F\'>, <class \'__main__.D\'>, <class \'__main__.B\'>, <class \'__main__.E\'>, <class \'__main__.C\'>,
<class \'__main__.A\'>, <class \'object\'>]
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def foo(self): print(\'from parent\') class Teacher(People): def __init__(self,name,age,sex,salary,level): # People.__init__(self,name,age,sex) # 指名道姓地调用People类的__init__函数 # 在Python3中 super().__init__(name,age,sex) # 调用父类的__init__的功能,实际上用的是绑定方法,只能调用一次父类 # 在Python2中 # super(Teacher,self).__init__(name,age,sex) self.salary=salary self.level=level def foo(self): super().foo() print(\'from child\') t=Teacher(\'egon\',18,\'male\',3000,10) t.foo()
方法一:父类名.父类方法()
方法二:super()
以上是关于面向对象——继承派生组合以及接口的主要内容,如果未能解决你的问题,请参考以下文章