继承
目标
● 单继承
● 多继承
面向对象三大特性
1、封装
根据职责将属性和方法封装到一个抽象的类中
2、继承
实现代码的重用,相同的代码不需要重复编写
3、多态
不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
01.单继承
1.1 继承的概念、语法和特点
**继承的概念:**子类拥有父类的方法和属性
不使用继承的动物类和狗类:
class Animal:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡")
class Dog:
def eat(self):
print("吃")
def drink(self):
print("喝")
def run(self):
print("跑")
def sleep(self):
print("睡")
def bark(self):
print("汪汪叫!!")
# 创建一个对象
wangcai = Dog()
wangcai.eat()
wangcai.drink()
wangcai.run()
wangcai.sleep()
wangcai.bark()
代码冗长,重复率大
1)继承的语法
class 类名(父类名):
pass
● 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
● 子类中应该根据职责,封装子类特有的属性和方法
运用继承的动物类和狗类(狗类继承自动物类):
class Dog(Animal):
def bark(self):
print("汪汪叫!!")
2)专业术语
● Dog类是 Animal类的子类, Animal类是 Dog类的父类, Dog类从 Animal类继承
● Dog类是 Animal类的派生类, Animal类是 Dog类的基类, Dog类从 Animal类派生
3)继承的传递性
● C类从B类继承,B类又从A类继承
● 那么C类就具有B类和A类的所有属性和方法
子类拥有父类以及父类的父类中封装的所有属性和方法
class Animal:
def eat(self):
print("吃...")
def drink(self):
print("喝...")
def run(self):
print("跑...")
def sleep(self):
print("睡...")
class Dog(Animal):
def bark(self):
print("汪汪叫!!")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞!!!")
# 创建一个对象
xiaotianquan = XiaoTianQuan()
xiaotianquan.eat()
xiaotianquan.drink()
xiaotianquan.run()
xiaotianquan.sleep()
xiaotianquan.bark()
1.2 方法的重写
● 子类拥有父类的所有方法和属性
● 子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
应用场景
● 当父类的方法实现不能满足子类的需求时,可以对方法进行重写(override)
重写父类的两种情况:
1、覆盖父类的方法
2、对父类方法进行扩展
1)覆盖父类的方法
● 如果在开发中,父类的方法实现和子类的方法实现,完全不同,就可以使用覆盖的方式,在子类中重新编写父类的方法实现
重写之后,在运行时,只会调用子类中的重写方法,而不会调用父类的封装方法
class Animal:
def eat(self):
print("吃...")
def drink(self):
print("喝...")
def run(self):
print("跑...")
def sleep(self):
print("睡...")
class Dog(Animal):
def bark(self):
print("汪汪叫!!")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞!!!")
def bark(self):
print("我是哮天犬,叫声更大哦!!")
# 创建一个对象
xtq = XiaoTianQuan()
xtq.bark()
2)对父类方法进行扩展
1、在子类中重写父类的方法
2、在需要的位置使用super().父类方法 来调用父类的方法执行
3、代码其他的位置针对子类的需求,编写子类特有的代码实现
关于super
● 在Python中,super是一个特殊的类
● super()就是使用super类创建出来的对象
● 最常使用的场景就是在重写父类方法时,调用在父类中封装的方法实现
class Animal:
def eat(self):
print("吃...")
def drink(self):
print("喝...")
def run(self):
print("跑...")
def sleep(self):
print("睡...")
class Dog(Animal):
def bark(self):
print("汪汪叫!!")
class XiaoTianQuan(Dog):
def fly(self):
print("我会飞!!!")
def bark(self):
# 1.针对子类特有的需求,编写代码
print("我是哮天犬,叫声更大!")
# 2.使用super(),调用原本在父类中封装的方法
super().bark()
# 3.增加其他子类的代码
print("$$$$$$$$")
# 创建一个对象
xtq = XiaoTianQuan()
xtq.bark()
1.3 父类的私有属性和私有方法
1、子类对象不能再自己的方法内部,直接访问父类的私有属性或私有方法
2、子类对象可以通过父类的公有方法间接访问到私有属性或私有方法
class A:
def __init__(self):
self.num1 = 100
self.__num2 = 200
def __test(self):
print("私有方法%d %d" % (self.num1, self.__num2))
def test(self):
print("父类的公有方法%d" % self.__num2)
self.__test()
class B(A):
def demo(self):
# 1、访问父类的私有属性
# print("访问父类的私有属性%d" % self.__num2)
# 2、调用父类的私有方法
# self.__test()
# 3、访问父类的公有属性
print("子类方法%d" % self.num1)
# 4、调用父类的公有方法
self.test()
# 创建一个子类对象
b = B()
print(b)
# 在外界不能直接调用私有属性和私有方法
# print(b.__num2)
# b.__test()
b.demo()
# 在外界访问父类的公有属性/调用公有方法
# print(b.num1)
# b.test()
02.多继承
概念
● 子类可以拥有多个父类,并且具有所有父类的属性和方法
● 例如:孩子会继承自己父亲和母亲的特性
语法
class 子类名(父类名1, 父类名2, …)
pass
class A:
def test(self):
print("test方法")
class B:
def deom(self):
print("demo方法")
class C(A, B):
"""多继承可以让子类对象,同时拥有多个父类的方法和属性"""
pass
# 创建子类对象
c = C()
c.test()
c.deom()
2.1 多继承的使用注意事项
如果父类之间存在同名的属性或者是方法,应该尽量避免使用多继承
class A:
def test(self):
print("a---test方法")
def deom(self):
print("a---demo方法")
class B:
def test(self):
print(" b---test方法")
def deom(self):
print("b---demo方法")
class C(B, A):
# class C(A, B):
pass
# 创建子类对象
c = C()
c.test()
c.deom()
Python中的MRO——方法搜索顺序
● Python中针对类提供了一个内置属性 __ mro __ 可以查看方法搜索顺序
● MRO 是method resolution order,主要用于在多继承时判断方法、属性的调用途径
print(C.__mro__)
输出结果
(<class ‘main.C’>, <class ‘main.B’>, <class ‘main.A’>, <class ‘object’>)
● 在搜索方法时,是按照MRO的输出结果从左至右的顺序查找的
● 如果在当前类中找到方法,就直接执行,找不到再搜索
● 如果直到最后一个类都没有找到,程序报错