• 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
     
  • 相关阅读:
    CREATE OPERATOR
    create_module
    一个LINUX狂人的语录(个人认为很精辟)
    jQuery 判断多个 input file 都不能为空
    Java实现 LeetCode 2 两数相加
    Java实现 LeetCode 2 两数相加
    Java实现 LeetCode 2 两数相加
    Java实现 蓝桥杯 算法提高 和谐宿舍2
    Java实现 蓝桥杯 算法提高 和谐宿舍2
    Java实现 蓝桥杯 算法提高 和谐宿舍2
  • 原文地址:https://www.cnblogs.com/surpass123/p/12678684.html
Copyright © 2020-2023  润新知