继承
- 在python中,任何一个类都有一个共同的父类叫object
- 继承:就是一个类可以获得另一个类中的成员属性和成员方法
- 作用: 减少代码,增加代码的复用功能,同时可以设置类与类之间的关系
单继承
-
语法:定义子类时在括号里写上父类名
-
继承与重用
- 重用:子类使用父类中的成员
- 被继承的类叫父类,也叫基类或超类,用于继承的类叫子类,也叫派生类
- 如果子类中定义的成员和父类成员如果相同,则优先使用子类成员
- 如果子类中没有就调用父类的
-
继承与派生
- 派生:子类在父类的基础上又新创建了自己需要的方法
- 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员进行代码重用
- 可以使用**父类名.父类成员(self,…)**的格式来调用父类成员
- 也可以使用**super().父类成员()**的格式调用,此时不需要传入self参数
- 派生:子类在父类的基础上又新创建了自己需要的方法
单继承
class Animal:
def __init__(self, name, kind, food, language):
self.name = name
self.kind = kind
self.food = food
self.language = language
def yell(self):
print("%s叫"% self.language)
def eat(self):
print("吃%s"% self.food)
class Cat(Animal):
def __init__(self, name, kind, food, language, eye_color):
self.eye_color = eye_color # 派生属性
Animal.__init__(self, name, kind, food, language)
# 也可以用super().__init__(name, kind, food, language),参数就不需要self了
def catch_mouse(self): # 派生方法
print("猫抓老鼠")
class Dog(Animal):
def look_after_house(self):
print("狗看家")
cat = Cat('阿猫','加菲猫','猫粮','喵喵')
dog = Dog('阿狗','yell泰迪','狗粮','汪汪')
cat.yell()
dog.yell()
喵喵叫
汪汪叫
例题
class Father:
def __init__(self):
self.fun()
def fun(self):
print('in Father')
class Son(Father):
def fun(self):
print('in Son')
son = Son()
in Son
结果分析:当self调用某个方法时,不要看self在哪个类里面,而是要看self是谁
- Son()执行时,触发
__init__
方法,由于Son中没有,因此执行父类Father中的 - 此时执行self.fun(),self是son,因此执行Son里面的fun
抽象类
规范的编程模式
- 抽象类:不能被实例化
- 写抽象类:
from abc import ABCMeta,abstractmethod
- 在这个类创建是指定
metaclass = ABCMeta
- 在希望子类继承的方法上加上
@abstractmethod
装饰器
- 使用抽象类:
- 继承这个类
- 必须实现这个类中被
@abstractmethod
装饰器装饰的方法
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod # 装饰后,继承Payment的类中必须要有pay方法
def pay(self):pass
class Wechatpay(Payment):
def pay(self):
print('微信支付')
class Applepay(Payment):
def pay(self):
print('Apple支付')
w1 = Wechatpay()
w2 = Applepay()
w1.pay()
w2.pay()
微信支付
Apple支付
多继承
- 语法:定义子类时在括号里写上多个父类名,用’,'隔开
单继承和多继承的优缺点
-
单继承:
- 传承有序 逻辑清晰 语法简单 隐患少
- 功能不能无限扩展,只能在当前唯一的继承链中扩展
-
多继承:
- 类的功能扩展方便
- 继承关系混乱
钻石继承
多个子类继承同一个父类,这些子类又被同一个类继承,于是继承关系图形成一个菱形图
- 关于多继承的mro
- mro就是多继承中,用于保存继承顺序的一个列表
- mro列表的计算原则: 像是深度优先和广度优先的结合,这篇文章解释的更详细
- 如果多个父类,则依据继承语法中括号内的顺序存放
- 最下面的子类先找继承的第一个父类,该父类接着找他继承的第一个父类,直到找到的父类有多个子类继承时,先不经过此父类,退回的最下面的还没走过的子类处,重复前面的过程
- 可以看到一个父类的子类一定是在此父类的前面先被遍历
- super不是单纯的找父类,而是按照mro中的顺序找
class A:
def f(self):
print("in A")
class B(A):
def f(self):
print("in B")
class C(A):
def f(self):
print("in C")
class D(B):
def f(self):
print("in D")
class E(C):
def f(self):
print("in E")
class G(B):
def f(self):
print("in E")
class F(D,E,G):
def f(self):
print("in F")
print(F.mro())
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.G'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
# F-->D-->E-->C-->G-->B-->A