zoukankan      html  css  js  c++  java
  • python 元类、单例模式

    内容目录:

    • 一、元类
    • 二、单例模式

    一、元类

    1 什么是元类:

    源自一句话:在python中,一切皆对象,而对象都是由类实例化得到的
    
    class OldboyTeacher:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def score(self):
        print('%s is scoring' %self.name)
        
    # tea1=OldboyTeacher('egon',18,'male')
    # # print(type(tea1))
    # print(type(OldboyTeacher))
    
    # 对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,那么OldboyTeacher也是一个对象,只要是对象
    # 都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type
    

    2.关系:

    1. 调用元类---->自定义的类
    2. 调用自定义的类---->自定义的对象
    

    3.创建自定义类

    自定义类的三个关键组成部分:

    1. 类名
    2. 类的基类们
    3. 类的名称空间
    
    class关键字创建自定义类的底层的工作原理,分为四步
    1. 先拿到类名:'OldboyTeacher'
    2. 再拿到类的基类们:(object,)
    3. 然后拿到类的名称空间???(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec)
    4. 调用元类实例化得到自定义的类: OldboyTeacher=type('OldboyTeacher',(object,),{...})
    
    不依赖class关键字创建一个自定义类
    # 1. 拿到类名
    class_name='OldboyTeacher'
    #2. 拿到类的基类们:(object,)
    class_bases=(object,)
    #3. 拿到类的名称空间
    class_dic={}
    class_body="""
    school = 'Oldboy'
    
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    
    def score(self):
        print('%s is scoring' %self.name)
    """
    exec(class_body,{},class_dic)
    print(class_dic)
    #4. 调用type得到自定义的类
    OldboyTeacher=type(class_name,class_bases,class_dic)
    
    print(OldboyTeacher)
    # print(OldboyTeacher.school)
    # print(OldboyTeacher.score)
    
    tea1=OldboyTeacher('egon',18,'male')
    print(tea1.__dict__)
    

    5.模板

    # class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类
    #     def __init__(self,class_name,class_bases,class_dic):
    #         print(self)
    #         print(class_name)
    #         print(class_bases)
    #         print(class_dic)
    #
    # class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...})
    #     school = 'Oldboy'
    #
    #     def __init__(self,name,age,sex):
    #         self.name=name
    #         self.age=age
    #         self.sex=sex
    #
    #     def score(self):
    #         print('%s is scoring' %self.name)
    
    控制类的产生
    1.类名必须用驼峰体
    2.类体必须有文档注释,且文档注释不能为空
    
    总结:对象之所以可以调用,是因为对象的类中有一个函数__call__
    推导:如果一切皆对象,那么OldboyTeacher也是一个对象,该对象之所可以调用,肯定是这个对象的类中也定义了一个函数__call__

    二、单例模式

    1.什么是单例

    单例:一个类只能产生一个实例
    

    2. 为什么要有单例:

    1.该类需要对象的产生
    2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
    

    3.实现单例的方法:

    # ----------------------------------------------------------------------
    # 方式一:模块
    
    class Songs():
        pass
    
    # s1 = Songs()
    # s2 = Songs()
    # print(s1, s2)
    
    # 对外提供的对象
    song = Songs()
    
    
    # ----------------------------------------------------------------------
    # 方式二:类方法
    
    class Songs():
        __instance = None
        @classmethod
        def getInstance(cls):
            # 对象没有创建返回,有直接返回
            if cls.__instance == None:
                cls.__instance = cls()
            return cls.__instance
    
    
    # 约定别用 类名() 来实例化对象,用类方法来获取唯一对象
    # s1 = Songs()
    # s2 = Songs()
    # print(s1, s2)
    
    s1 = Songs.getInstance()
    s2 = Songs.getInstance()
    print(s1, s2)
    
    # ----------------------------------------------------------------------
    # 方式三:类初始化时对标志进行判断
    
    class Songs:
        __instance = None
        def __new__(cls, song_name, *args, **kwargs):
            if cls.__instance == None:
                cls.__instance = object.__new__(cls)
                cls.__instance.song_name = song_name
            return cls.__instance
    
        def change_song(self, song_name):
            self.song_name = song_name
    
    s1 = Songs('菊花爆满山')
    s2 = Songs('感觉身体被掏空')
    print(s1.song_name, s2.song_name)  # 菊花爆满山  菊花爆满山
    s2.change_song('感觉身体被掏空')
    print(s1.song_name, s2.song_name)  # 感觉身体被掏空 感觉身体被掏空
    
    # ----------------------------------------------------------------------
    # 方式四: 装饰器装饰类
    
    def outer(cls):
        _instance = None
        def inner(*args, **kwargs):
            nonlocal _instance
            if _instance == None:
                _instance = cls(*args, **kwargs)
            return _instance
        return inner
    
    @outer  # Songs = outer(Songs)
    class Songs:
        pass
    
    
    s1 = Songs()
    s2 = Songs()
    print(s1, s2)
    
    
    # ----------------------------------------------------------------------
    # 方式五: 元类实现
    class SingleMeta(type):
        __instance = None
        def __call__(cls, *args, **kwargs):
            if SingleMeta.__instance == None:
                SingleMeta.__instance = object.__new__(cls)
                cls.__init__(SingleMeta.__instance, *args, **kwargs)
            return SingleMeta.__instance
    
    
    class Songs(metaclass=SingleMeta):
        def __init__(self):
            pass
        pass
    
    
    s1 = Songs()
    s2 = Songs()
    print(s1, s2)
    
    
  • 相关阅读:
    20145202马超《网络对抗》Exp9*_* Web安全基础实践
    20145202马超《java》【课堂实验】P98测试
    20145202马超 2016-2017-2 《Java程序设计》第11周学习总结
    20145202马超《网络对抗》Exp8 Web基础
    20145202马超 2016-2017-2 《Java程序设计》第三次实验
    20145202马超 2016-2017-2 《Java程序设计》第10周学习总结
    20145202马超《网络对抗》Exp7 网络欺诈技术防范
    20145202马超 2016-2017-2 《Java程序设计》第二次实验
    20145202马超 2016-2017-2 《Java程序设计》第9周学习总结
    20145202马超《网络对抗》Exp6 信息搜集与漏洞扫描
  • 原文地址:https://www.cnblogs.com/xt12321/p/10784478.html
Copyright © 2011-2022 走看看