咱们都知道Python面向对象编程有三大特征,继承,封装和多态,下面几篇问题,咱们会分别讲述着几大特征。python
今天说的是继承,若是有编程基础的人对这个词应该不会陌生,继承是一种建立新类的方式,新建的类能够继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类,而子类会“”遗传”父类的属性(数据属性和函数属性),从而解决代码重用问题。编程
上面这段话就是继承的概念和使用继承所要达到的目的。bash
下面咱们来看看具体代码案例,继续的大体写法就是函数
子类名(父类1,父类2,。。。)oop
Python是能够实现对继承的,有些编程语法是只能单继承。ui
class ParentClass:
name= '父类'
def __init__(self,size,color):
self.size = size
self.color = color
def fun(self):
print('我来自父类')
class SubClass(ParentClass):
name = '子类'
pass
#实例化对象
s1 = SubClass('30','red')
#{'size': '30', 'color': 'red'} 若是子类没有构造方法的话,子类属性会找到父类的构造方法,继承父类的数据属性
print(s1.__dict__)
#(<class 'object'>,) python3中统一都是新式类,因此若是不加继承的父类,默认的父类是object类
print(ParentClass.__bases__)
#(<class '__main__.ParentClass'>,) 子类的父类
print(SubClass.__bases__)
# "我来自父类" 子类对象调用父类的方法
s1.fun()
#子类对象调用数据属性,会先在子类中找,若是找不到会去父类的做用域里面找
#这里子类里面定义了name属性因此结果是: 子类
#若是子类里面没有定name,结果就是:父类
print(s1.name)
复制代码
这段是继承大体的用法,子类能够继承父类的数据属性和函数属性。下面咱们说说使用继承的好处及代码重用和重写,组合的用法编码
代码重用spa
咱们如今有2个类猫和狗,它们都是动物,那若是咱们要描述猫和狗这2个类的话,咱们会存在大量的重复代码,以下code
class Cat:
def cry(self):
print('喵喵')
def eat(self):
print('吃')
def run(self):
print('跑')
def jump(self):
print('跳')
class Dog:
def cry(self):
print('汪汪')
def eat(self):
print('吃')
def run(self):
print('跑')
def jump(self):
print('跳')
cat1 = Cat()
dog1 = Dog()
cat1.cry()
dog1.cry()
复制代码
上面2个类也许除了cry方法,其余的方法都是同样的,都猫和狗赞成的动做,那像上面那样写,就会出现大量的重复代码,下面咱们用继承来改写对象
class animal:
def cry(self):
print('动物叫')
def eat(self):
print('吃')
def run(self):
print('跑')
def jump(self):
print('跳')
class Cat(animal):
def cry(self):
print('喵喵')
class Dog(animal):
def cry(self):
print('汪汪')
cat1 = Cat()
dog1 = Dog()
cat1.cry() #喵喵
dog1.cry() #汪汪
cat1.eat() #吃
dog1.eat() #吃
复制代码
上面咱们定义了一个animal的父类,把子类的相同部分放入父类,子类就能够用继承的方式来调用父类的函数属性或者说方法了,而不用再类里面再重复编码。
其实上面的例子咱们已经用到重写,就是父类定义了一个方法,可是子类和父类的方法实现不同,要达到另一个功能,比较上面
父类的cry方法时: ‘动物叫’
子类Cat的cry要实现:‘喵喵叫’
子类Dog的cry要实现:‘汪汪叫’
这种状况就要使用重写
class animal:
def cry(self):
print('动物叫')
def eat(self):
print('吃')
def run(self):
print('跑')
def jump(self):
print('跳')
class Cat(animal):
def cry(self):
print('喵喵')
class Dog(animal):
def cry(self):
print('汪汪')
cat1 = Cat()
dog1 = Dog()
cat1.cry() #喵喵 重写父类cry方法
dog1.cry() #汪汪 重写父类cry方法
复制代码
class animal:
def cry(self):
print('动物叫')
def eat(self):
print('吃')
def run(self):
print('跑')
def jump(self):
print('跳')
class Cat(animal):
def cry(self):
print('喵喵')
def swoop(self): #定义子类的方法
print('飞扑')
cat1 = Cat()
cat1.swoop()
复制代码
4.类的组合,组合指的是,在一个类中以另一个类的对象做为数据属性,称为类的组合,当类之间有显著不一样,而且较小的类是较大的类所须要的组件时,用组合比较好.
class School:
def __init__(self,name,addr):
self.name=name
self.addr=addr
def recruit(self):
print('%s xxx计算机学校订在招生' %self.name)
class Course:
def __init__(self,name,price,period,School):
self.name=name
self.price=price
self.period=period
self.school=School #实现Course和School的组合
s1=School('xxx计算机学校','北京')
s2=School('xxx计算机学校','南京')
s3=School('xxx计算机学校','上海')
msg=''' 1 xxx计算机学校 北京校区 2 xxx计算机学校 南京校区 3 xxx计算机学校 上海校区 '''
while True:
print(msg)
menu={
'1':s1,
'2':s2,
'3':s3
}
choice=input('选择学校>>: ')
school_obj=menu[choice]
name=input('课程名>>: ')
price=input('课程费用>>: ')
period=input('课程周期>>: ')
new_course=Course(name,price,period,school_obj)
print('课程【%s】属于【%s】学校' %(new_course.name,new_course.school.name)) #实现Course和School的组合
复制代码
5.Python实现接口
接口就是定义抽象函数,不作具体函数实现,起到规范子类的做用,让子类必须实现接口的抽象函数。接口提取了一群类共同的函数,能够把接口当作一个函数的集合。而后让子类去实现接口中的函数。这么作的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么全部的这些类产生的对象在使用时,从用法上来讲都同样。
归一化的好处在于:
归一化让使用者无需关心对象的类是什么,只须要的知道这些对象都具有某些功能就能够了,这极大地下降了使用者的使用难度。
归一化使得高层的外部使用者能够不加区分的处理全部接口兼容的对象集合
下面上代码
import abc #利用abc模块实现抽象类
class Interface(metaclass=abc.ABCMeta):
@abc.abstractclassmethod #抽象方法,不作具体实现
def test1(self):
pass
@abc.abstractclassmethod
def test2(self):
pass
class SubClass(Interface):
def test1(self):
print('实现抽象方法1')
def test2(self):
print('实现抽象方法2')
s1 = SubClass()
复制代码
若是咱们子类里面不实现具体的抽象函数,会报错
import abc #利用abc模块实现抽象类
class Interface(metaclass=abc.ABCMeta):
@abc.abstractclassmethod #抽象方法,不作具体实现
def test1(self):
pass
@abc.abstractclassmethod
def test2(self):
pass
class SubClass(Interface):
def test1(self):
print('实现抽象方法1')
#不实现test2方法
s1 = SubClass()
复制代码
报错信息:
Traceback (most recent call last): File "C:/Users/aryin/Desktop/mysite2/继承.py", line 16, in s1 = SubClass() TypeError: Can't instantiate abstract class SubClass with abstract methods test2
6.类继承的顺序,根据类的MRO属性
class A:
def test(self):
print('A')
class B(A):
def test(self):
print('B')
class C(A):
def test(self):
print('C')
class D(B):
def test(self):
print('D')
class E(C):
def test(self):
print('E')
class F(D,E):
def test(self):
print('F')
# (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
print(F.__mro__)
复制代码
类继承是是按照MRO属性里面的顺序去调用父类的属性
7.子类调用父类的方法,是经过super函数来实现的,在复杂的类继承关系中,super()的取值是按照上面的MRO里面的顺序来定的。
class animal:
def __init__(self,name,type,size,color):
self.name = name
self.type = type
self.size = size
self.color = color
def cry(self):
print('动物叫')
def eat(self):
print('吃')
class Cat(animal):
def __init__(self,name,type,size,color,age):
super().__init__(name,type,size,color) #调用父类的构造函数,这是super最经常使用的地方
self.age = age
def cry(self):
super().cry() #子类从新了父类的方法,可是同时又要实现父类中cry方法
print('喵喵')
cat1 = Cat('毛球','波斯猫',10,'白色','5岁')
# 动物叫
# 喵喵
cat1.cry()
复制代码