29.3-Mixin

作者: BeautifulSoulpy | 来源:发表于2019-12-19 17:34 被阅读0次

    你坚持什么,付出什么,才会得到什么!
    你的人生不需要别人来买单,也自然不需要在乎别人的脸色过生活!

    总结:

    1. 函数定义名为 内建函数会导致冲突,类中函数定义不会;
    2. Python的特点:字典,装饰器,生成器,后面大量的库中 会使用;

    Python 非常灵活,引入多继承后,代码可能不可控制; 应当避免使用多继承;

    (多继承要求水平高)在水平上来的时候,可以尝试使用;

    多继承的控制——Mixin

    Mixin类

    Mixin本质上就是多继承实现的。
    Mixin体现的是一种组合的设计模式。
    在面向对象的设计中,一个复杂的类,往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多的类组
    合在一起。
    从设计模式的角度来说,多组合,少继承。
    Mixin类的使用原则
    Mixin类中不应该显式的出现init初始化方法
    Mixin类通常不能独立工作,因为它是准备混入别的类中的部分功能实现
    Mixin类的祖先类也应是Mixin类

    
    class Document:
        def __init__(self,content):
            self.content = content
            
        def print(self):   # 继承后要覆盖的类;  只定义,不实现,抽象方法; 
            raise NotYmplementError('未实现') # 异常,未实现异常;
            
    class Word(Document):pass # 不能修改,第三方提供的;
    class Pdf(Document):pass
    
    # OCP
    class PrintableWord(Word):
        def print(self):
            print('word:',self.content)  # word 提供自己文件格式的打印;
            
    class PrintablePdf(Pdf):
        def print(self):
            print('Pdf:',self.content)
            
    pw = PrintableWord('test.word')
    pw.print()
    pp = PrintablePdf('test.pdf')
    pp.print()
    #-----------------------------------------------------------------------------------------------------------------------
    word: test.word
    Pdf: test.pdf
    
    

    看似不错,如果需要还要提供其他能力,如何继承?
    应用于网络,文档应该具备序列化的能力,类上就应该实现序列化。
    可序列化还可能分为使用pickle、json、messagepack等。

    这个时候发现,为了增加一种能力,就要增加一次继承,类可能太多了,继承的方式不是很好了。
    功能太多,
    A类需要某几样功能,B类需要另几样功能,它们需要的是多个功能的自由组合,继承实现很繁琐。

    装饰器
    用装饰器增强一个类,把功能给类附加上去,那个类需要,就装饰它;
    优点:
    简单方便,在需要的地方动态增加,直接使用装饰器。
    可以为类灵活的增加功能。

    # 装饰器:怎么用就这么写,反过来推;
    class Document:
        def __init__(self,content):
            self.content = content
            
        def print(self):   # 继承后要覆盖的类;  只定义,不实现,抽象方法; 
            raise NotYmplementError('未实现') # 异常,未实现异常;
            
    class Word(Document):pass # 不能修改,第三方提供的;
    class Pdf(Document):pass
    
    # OCP
    def printable(cls):  # 装饰器
        def _print(self):   # 函数定义名为 内建函数会导致冲突,类不会;
            print("{}:{}".format(type(self).__name__,self.content))
        cls.print = _print
        return cls
    
    @printable
    class PrintableWord(Word):   # 为 word 提供打印功能;
        def print(self):
            print('word:',self.content)  # word 提供自己文件格式的打印;
    @printable  
    class PrintablePdf(Pdf):
        def print(self):
            print('Pdf:',self.content)
            
    pw = PrintableWord('test.word')
    pw.print()
    pp = PrintablePdf('test.pdf')
    pp.print()
    print(PrintableWord.__dict__)
    #---------------------------------------------------------------------------------------------
    PrintableWord:test.word
    PrintablePdf:test.pdf
    {'__module__': '__main__', 'print': <function printable.<locals>._print at 0x0000020658DAEB70>, '__doc__': None}
    
    
    # 增加功能写法2: 增加属性写法;
    #@printable  
    class PrintablePdf(Pdf): pass
    #     def print(self):
    #         print('Pdf:',self.content)
    PrintablePdf.print = lambda self:print('!!!!!!!!')
    
    pp = PrintablePdf('test.pdf')
    pp.print()
    print(PrintablePdf.__dict__)
    #---------------------------------------------------------------------
    PrintableWord:test.word
    !!!!!!!!
    {'__module__': '__main__', '__doc__': None, 'print': <function <lambda> at 0x0000020658DC9D90>}
    
    

    Mixin

    Mixin类就是其它类混合进来,同时带来了类的属性和方法。
    这里看来Mixin类和装饰器效果一样,也没有什么特别的。但是Mixin是类,就可以继承

    class Document:
        def __init__(self,content):
            self.content = content
            
        def print(self):   # 继承后要覆盖的类;  只定义,不实现,抽象方法; 
            raise NotYmplementError('未实现') # 异常,未实现异常;
            
    class Word(Document):pass # 不能修改,第三方提供的;
    class Pdf(Document):pass
    
    # OCP
    def printable(cls):  # 装饰器
        def _print(self):   # 函数定义名为 内建函数会导致冲突,类不会;
            print("{}:{}".format(type(self).__name__,self.content))
        cls.print = _print
        return cls
    
    class PrintableMixin:
        def print(self):
            print("{}:{}".format(type(self).__name__,self.content))
            
    class PrintablePdfMixin(PrintableMixin,Pdf):pass
    class PrintableWordMixin(PrintableMixin,Word):pass
    # @printable  
    # class PrintablePdf(Pdf): pass
    #     def print(self):
    #         print('Pdf:',self.content)
    
    pdfm = PrintablePdfMixin('test mixin')
    pdfm.print()
    print(pdfm.__class__.mro())
    
    pwm = PrintableWordMixin('test mixin word!')  # 缺什么就补什么;
    pwm.print()
    #-------------------------------------------------------------------------------------------------
    PrintablePdfMixin:test mixin
    [<class '__main__.PrintablePdfMixin'>, <class '__main__.PrintableMixin'>, <class '__main__.Pdf'>, <class '__main__.Document'>, <class 'object'>]
    PrintableWordMixin:test mixin word!
    
    
    class Document:
        def __init__(self,content):
            self.content = content
            
        def print(self):   # 继承后要覆盖的类;  只定义,不实现,抽象方法; 
            raise NotYmplementError('未实现') # 异常,未实现异常;
            
    class Word(Document):pass # 不能修改,第三方提供的;
    class Pdf(Document):pass
    
    def printable(cls):  # 装饰器
        def _print(self):   # 函数定义名为 内建函数会导致冲突,类不会;
            print("{}:{}".format(type(self).__name__,self.content))
        cls.print = _print
        return cls
    
    
    class PrintableMixin:  # 简单打印模式
        def print(self):
            print("{}:{}".format(type(self).__name__,self.content))
            
    class SuperPrintableMixin(PrintableMixin):  # 复杂打印模式,再做继承,再增强;
        def print(self):
            print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
            super().print()
            print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
            
    class SuperPrintablePdfMixin(SuperPrintableMixin,Pdf):pass
    class SuperPrintableWordMixin(SuperPrintableMixin,Word):pass
    # @printable  
    # class PrintablePdf(Pdf): pass
    #     def print(self):
    #         print('Pdf:',self.content)
    
    pdfm = PrintablePdfMixin('test mixin')
    pdfm.print()
    print(pdfm.__class__.mro())
    
    pwm = PrintableWordMixin('test mixin word!')  # 缺什么就补什么;
    pwm.print()
    #---------------------------------------------------------------------------------------------------------
    PrintablePdfMixin:test mixin
    [<class '__main__.PrintablePdfMixin'>, <class '__main__.PrintableMixin'>, <class '__main__.Pdf'>, <class '__main__.Document'>, <class 'object'>]
    PrintableWordMixin:test mixin word!
    
    

    Mixin本质上就是多继承实现的。
    Mixin体现的是一种组合的设计模式。
    在面向对象的设计中,一个复杂的类,往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多的类组
    合在一起。
    从设计模式的角度来说,多组合,少继承。

    Mixin类的使用原则

    1. Mixin类中不应该显式的出现_init_初始化方法
    2. Mixin类通常不能独立工作,因为它是准备混入别的类中的部分功能实现
    3. Mixin类的祖先类也应是Mixin类
    4. 使用时,Mixin类通常在继承列表的第一个位置,
      例如 class PrintableWord(PrintableMixin, Word): pass

    Mixin类和装饰器
    这两种方式都可以使用,看个人喜好。如果还需要继承就得使用Mixin类的方式。

    练习

    1、Shape基类,要求所有子类都必须提供面积的计算,子类有三角形、矩形、圆。


    import math
    class Shape:  # 形状类;
        @property
        def area(self):
            raise NotImplementedError('基类未实现')
            
    class Triangle(Shape):
        def __init__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c
            
        @property
        def area(self):
            p = (self.a+self.b+self.c)/2
            return math.sqrt(p*(p-self.a)*(p-self.b)*(p-self.c))
        
    class Rectangle(Shape):
        def __init__(self, width, height):
            self.width = width
            self.height = height
            
        @property
        def area(self):
            return self.width * self.height
        
    class Circle(Shape):
        def __init__(self,redius):
            self.r = redius
            
        @property
        def area(self):
            return self.r * self.r * math.pi
    
    c = Circle(4)
    print(c.area)
    #---------------------------------------------------------------------------------------------
    50.26548245743669
    
    

    2、圆类的数据可序列化

    import math,json,msgpack
    class Shape:  # 形状类;
        @property
        def area(self):
            raise NotImplementedError('基类未实现')
            
    class SerializableMixin:  # Mixin 写法;
        def serialize(self,m='json'):
            if m == 'json':return json.dumps(self.__dict__)
            elif m == 'msgpack':return msgpack.dumps(self.__dict__)
            else:raise NotImplementedError
            
    class Circle(Shape):
        def __init__(self,redius):
            self.r = redius
            
        @property
        def area(self):
            return self.r * self.r * math.pi
    class SerializableCircleMixin(SerializableMixin,Circle):pass
    
    scm = SerializableCircleMixin(4)
    print(scm.area)
    print(scm.__dict__)
    print(scm.serialize('msgpack'))
    #-------------------------------------------------------------------
    50.26548245743669
    {'r': 4}
    b'\x81\xa1r\x04'
    
    

    作业 : 链表的实现

    相关文章

      网友评论

        本文标题:29.3-Mixin

        本文链接:https://www.haomeiwen.com/subject/pmzpnctx.html