zoukankan      html  css  js  c++  java
  • 面向对象之元类,单例

    元类

    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)
     方式三:基于__new__
    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)

     __init__,__new__,__call__的区别

     
  • 相关阅读:
    Step by step Dynamics CRM 2013安装
    SQL Server 2012 Managed Service Account
    Step by step SQL Server 2012的安装
    Step by step 活动目录中添加一个子域
    Step by step 如何创建一个新森林
    向活动目录中添加一个子域
    活动目录的信任关系
    RAID 概述
    DNS 正向查找与反向查找
    Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
  • 原文地址:https://www.cnblogs.com/wangtenghui/p/10816470.html
Copyright © 2011-2022 走看看