zoukankan      html  css  js  c++  java
  • day---30 Mixins机制与重用父类功能的两种方式

    1、python多继承存在的问题


    一个子类可以继承多个父类,这样的设计为人们所诟病,主要是因为:

    1、容易导致可恶的菱形问题
    2、在人们的世界观中,继承是"is-a"的关系

    但在实际开发需求中,一个类还是有继承多个类的需求的,比如以下交通工具:

    民航飞机、直升飞机、轿车,这三者都是交通工具,所以可以定义一个Vehicle作为他们的父类,

    但是前两者有飞行功能,而第三者没有,这就需要定义一个含有飞行功能的类让前两者继承。

    为了解决多继承带来的可读性问题,python提供了一种规范机制——Mixins机制

    2、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惯用的套路
    if hasattr(os, "fork"):
        class ForkingUDPServer(ForkingMixIn, UDPServer): pass
        class ForkingTCPServer(ForkingMixIn, TCPServer): pass
    
    class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
    class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

    使用Mixins机制的注意事项:

    1、首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀
    2、然后,它不依赖于子类的实现
    3、最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。

    3、重用父类方法的两种方式


     (1)方式一:指名道姓的使用某一类的函数

    >>> class Teacher(People):
    ...     def __init__(self,name,sex,age,title):
    ...         People.__init__(self,name,age,sex) #调用的是函数,因而需要传入self
    ...         self.title=title
    ...     def teach(self):
    ...         print('%s is teaching' %self.name)

    (2)方式二:super()

    调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照MRO规定的顺序向后查找

    在Python2中super的使用需要完整地写成super(自己的类名,self) ,而在python3中可以简写为super()

    >>> class Teacher(People):
    ...     def __init__(self,name,sex,age,title):
    ...         super().__init__(name,age,sex) #调用的是绑定方法,自动传入self
    ...         self.title=title
    ...     def teach(self):
    ...         print('%s is teaching' %self.name)

    区别:

    方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找
    >>> #A没有继承B
    ... class A:
    ...     def test(self):
    ...         super().test()
    ... 
    >>> class B:
    ...     def test(self):
    ...         print('from B')
    ... 
    >>> class C(A,B):
    ...     pass
    ... 
    >>> C.mro() # 在代码层面A并不是B的子类,但从MRO列表来看,属性查找时,就是按照顺序C->A->B->object,B就相当于A的“父类”
    [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,<class ‘object'>]
    >>> obj=C()
    >>> obj.test() # 属性查找的发起者是类C的对象obj,所以中途发生的属性查找都是参照C.mro()
    from B
     
  • 相关阅读:
    火狐插件火狐黑客插件将Firefox变成黑客工具的七个插件
    memcache安装环境:WINDOWS 7
    PHP正则表达式
    968. 监控二叉树 力扣(困难) dfs 官方说DP
    375. 猜数字大小 II 力扣(中等) 区间动态规划、记忆化搜索
    629. K个逆序对数组 力扣(困难) 区间动态规划
    剑指 Offer 51. 数组中的逆序对 力扣(困难) 巧用归并排序算法
    488. 祖玛游戏 力扣(困难) dfs
    16. 最接近的三数之和 力扣(中等) 双指针
    319. 灯泡开关 力扣(中等) 数论
  • 原文地址:https://www.cnblogs.com/surpass123/p/12678684.html
Copyright © 2011-2022 走看看