• DAY 20 PYTHON入门


    一、继承
    继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,
    新建的类可称为子类或派生类,父类又可称为基类或超类。

    在Python2中有经典类与新式类之分,没有显式地继承object类的类,以及该类的子类,都是经典类,显式地继承object的类,
    以及该类的子类,都是新式类。而在Python3中,即使没有显式地继承object,也会默认继承该类。

    要找出类与类之间的继承关系,需要先抽象,再继承。抽象即总结相似之处,总结对象之间的相似之处得到类,总结类与类之间的相似之处就可以得到父类。
    基于抽象的结果,我们就找到了继承关系。

    类与类之间的继承指的是什么‘是’什么的关系(比如人类,猪类,猴类都是动物类)。子类可以继承/遗传父类所有的属性,因而继承可以用来解决类与类之间的代码重用性问题。
    有了继承关系,对象在查找属性时,先从对象自己的__dict__中找,如果没有则去子类中找,然后再去父类中找……

    父类如果不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有的


    继承的应用:
    对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,
    MRO列表的构造是通过一个C3线性化算法来实现的,我们无需深究该算法的数学原理,它实际上就是合并所有父类的MRO列表,且在查找属性时,
    Python会基于MRO列表按照从左到右的顺序依次查找基类,直到找到第一个匹配这个属性的类为止。

    在Python中子类可以同时继承多个父类,在子类继承了多个父类时,经典类与新式类会有不同MRO,分别对应属性的两种查找方式:深度优先和广度优先

    二、派生与方法重用
    子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找,例如每个老师还有职称这一属性,我们就需要在Teacher类中定义该类自己的__init__覆盖父类的
    方法一:“指名道姓”地调用某一个类的函数。
    方法二:super()
    这两种方式的区别是:方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找

    调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照MRO规定的顺序向后查找
    提示:在Python2中super的使用需要完整地写成super(自己的类名,self) ,而在python3中可以简写为super()。

    关于在子类中重用父类功能的这两种方式,使用任何一种都可以,但是在最新的代码中还是推荐使用super()

    三、组合
    在一个类中以另外一个类的对象作为数据属性,称为类的组合。组合与继承都是用来解决代码的重用性问题。
    不同的是:继承是一种“是”的关系,比如老师是人、学生是人,当类之间有很多相同的之处,应该使用继承;
    而组合则是一种“有”的关系,比如老师有生日,老师有多门课程,当类之间有显著不同,并且较小的类是较大的类所需要的组件时,应该使用组合。

    四、mixins机制
    Python语言可没有接口功能,但Python提供了Mixins机制,简单来说Mixins机制指的是子类混合(mixin)不同类的功能,
    而这些类采用统一的命名规范(例如Mixin后缀),以此标识这些类只是用来混合功能的,并不是用来标识子类的从属"is-a"关系的,
    所以Mixins机制本质仍是多继承,但同样遵守”is-a”关系。如:
    class Vehicle: # 交通工具
    pass

    class FlyableMixin:
    def fly(self):
    '''
    飞行功能相应的代码
    '''
    print("I am flying")

    class CivilAircraft(FlyableMixin, Vehicle): # 民航飞机
    pass

    class Helicopter(FlyableMixin, Vehicle): # 直升飞机
    pass

    class Car(Vehicle): # 汽车
    pass

    # ps: 采用某种规范(如命名规范)来解决具体的问题是python惯用的套路

    使用Mixin类实现多重继承要非常小心:
    #首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀
    #其次它必须责任单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin,为了保证遵循继承的“is-a”原则,只能继承一个标识其归属含义的父类
    #然后,它不依赖于子类的实现
    #最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了)

    Mixins是从多个类中重用代码的好方法,但是需要付出相应的代价,我们定义的Minx类越多,子类的代码可读性就会越差,而且,
    在继承的层级变多时,代码阅读者在定位某一个方法到底在何处调用时会晕头转向,如下。

    class Displayer:
    def display(self, message):
    print(message)

    class LoggerMixin:
    def log(self, message, filename='logfile.txt'):
    with open(filename, 'a') as fh:
    fh.write(message)

    def display(self, message):
    super().display(message) # super的用法请参考下一小节
    self.log(message)

    class MySubClass(LoggerMixin, Displayer):
    def log(self, message):
    super().log(message, filename='subclasslog.txt')

    obj = MySubClass()
    obj.display("This string will be shown and logged in subclasslog.txt")

    # 属性查找的发起者是obj,所以会参照类MySubClass的MRO来检索属性
    #[<class '__main__.MySubClass'>, <class '__main__.LoggerMixin'>, <class '__main__.Displayer'>, <class 'object'>]
    # 1、首先会去对象obj的类MySubClass找方法display,没有则去类LoggerMixin中找,找到开始执行代码
    # 2、执行LoggerMixin的第一行代码:执行super().display(message),参照MySubClass.mro(),super会去下一个类即类Displayer中找,找到display,开始执行代码,打印消息"This string will be shown and logged in subclasslog.txt"
    # 3、执行LoggerMixin的第二行代码:self.log(message),self是对象obj,即obj.log(message),属性查找的发起者为obj,所以会按照其类MySubClass.mro(),即MySubClass->LoggerMixin->Displayer->object的顺序查找,
    在MySubClass中找到方法log,开始执行super().log(message, filename='subclasslog.txt'),super会按照MySubClass.mro()查找下一个类,在类LoggerMixin中找到log方法开始执行,最终将日志写入文件subclasslog.txt

  • 相关阅读:
    前端
    【转帖】今天看到一篇有意思的文章:程序员的十楼层。看看自己在第几层
    jquery 验证表单
    JavaWeb--Servlet
    JDBC——数据库连接池(connection pool) DBCP&&C3P0
    JDBC——批量处理JDBC语句提高处理速度
    JDBC——数据库的隔离级别
    JDBC——数据库事务
    JDBC——取得数据库自动生成的主键
    JDBC——建立数据库连接
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14267697.html
Copyright © 2020-2023  润新知