美文网首页
day33元类\单例模式

day33元类\单例模式

作者: 荭鲤鱼与緑鲤鱼与驴 | 来源:发表于2020-08-20 17:26 被阅读0次

    Ⅰ      元类

        类的爹就是元类 #很通俗易懂

        而在python中又有一切皆对象说法

        那么类是如何成为对象的呢?即调用元类,得到对象(类,或者说自定义的类)

        默认的元类的type,默认情况下我们用class关键字定义的类都是由type产生的

    # python中一切皆对象

    # 元类介绍

    # 元类=>OldboyTeacher类 =>obj 对象

    class OldboyTeacher(object):

        school = 'oldboy'

        def __init__(self, name, age):

            self.name = name

            self.age = age

        def say(self):

            print('>>>>')

    obj = OldboyTeacher('egon', 16)  # 调用类OldboyTeacher类得到类的对象obj

                        # 调用元类得到OldboyTeacher类(对象)

    问题又来了,class关键字是如何产生类的呢?

    # class关键字底层做了哪些事

    # 先拿到一个类名

    class_name = 'Oldboy'

    # 然后拿到类的父亲

    class_bases = (object,)

    # 再运行类体代码,将产生的名字放到名称空间中

    class_dic = {}

    class_body = """

    school = 'oldboy'

    def __init__(self,name,age):

        self.name = name

        self.age = age

    def say(self):

        print('>>>')

    """

    exec(class_body,{},class_dic)

    print(class_dic)

    # 调用元类(传入类的三大要素:类名,基类,类的名称空间,得到一个元类的对象

    #  然后将元类的对象赋值给变量名OldboyTeacher就是我们用class自定义的那个类)

    OldboyTeacher = type(class_name,class_bases,class_dic)

    自定义元类

    只有继承了type类的类才是自定义的元类

    class Mymeta(type):

        pass

    #1>先拿到一个类名:'egon'

    #2>然后拿到类的父亲:(object,)

    #3>再运行类体代码,将产生的名字放到名称空间中{...}

    #4>调用元类(传入类的三大要素:类名,基类,类的名称空间)

    # 得到一个元类的对象,然后将元类的对象赋值给变量名

    单例模式

    一个类被多次调用产生的多个对象,但是对象内的数据都是一样的,这样就额外占用了内存空间,解决这个问题的方式就称为类的单例模式

    class MyQLE():

        def __init__(self,name,age):

            self.name = name

            self.age = age

    obj = MyQLE('egon',19)

    obj2 = MyQLE('egon',19)

    print(obj)  # 两个对象数据一样,但是占用了两份内存空间

    print(obj2)

    方式一:classmethod功能

    import setting  # 例如从一个文件中取出固定的值

    class MyQLE():

        __instance = None  # 定义一个变量

        def __init__(self,name,age):

            self.name = name

            self.age = age

        @classmethod

        def singleton(cls):  # 写成类方法

            if cls.__instance:  # 调用的时候判断变量有值,直接返回已存在的值,不用二次调用产生新的

                return cls.__instance

            else:

                cls.__instance = cls(setting.name,setting.age)  # 如果没有,将类实例化得到对象并赋值,返回

                return cls.__instance

    obj2 = MyQLE.singleton()

    print(obj2)

    obj = MyQLE.singleton()

    print(obj)

    方式二:使用元类

    # 方式二 : 使用元类

    import setting

    class Mymeta(type):

        __instance = None

        def __init__(self,class_name,class_banses,class_dic):

            self.__instance = object.__new__(self) #类的对象

            self.__init__(self.__instance,setting.name,setting.age)

        def __call__(self, *args, **kwargs):

            if args or kwargs:

                obj = object.__new__(self)

                self.__init__(obj,*args, **kwargs)

                return obj

            else:

                return self.__instance

    class MySQL(metaclass=Mymeta):

        def __init__(self,name,age):

            self.name = name

            self.age = age

    obj2 = MySQL()

    obj3 = MySQL()

    print(obj2)

    print(obj3)

    方式三:使用装饰器

    # 方式三: 使用装饰器

    import setting

    def outter(func):

        _instance = func(setting.name,setting.age)

        def wrapper(*args,**kwargs):

            if args or kwargs:

                return func(*args,**kwargs)

            else:

                return _instance

        return wrapper

    @outter

    class MySQL:

        def __init__(self,name,age):

            self.name = name

            self.age = age

    obj1 = MySQL()

    obj2 = MySQL()

    print(obj2)

    print(obj1)

    相关文章

      网友评论

          本文标题:day33元类\单例模式

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