zoukankan      html  css  js  c++  java
  • 元类补充以及单例模式

    元类补充

    object._new_

    class Person():
        def __init__(self,name,age):
            print('__init__')
            self.name=name
            self.age=age
        def __new__(cls, *args, **kwargs):
            print('__new__')
            #生成一个Person类的空对象
            return object.__new__(cls)
     
    p=Person('lqz',19)
    print(p)
    

    会发现结果为:

    _new_
    __init__
    <__main__.Person object at 0x000002217E7099E8>

    为什么先会调用__new__呢?

    因为Person加括号先调用了type类里的_call_,然后__call__调用了Person类的__new__

    _new_ 和__init__

    _new_ 创建空对象

    _init_ 初始化空对象

    object._new_(Person) :生成Person类的对象 空的

    type._new_(cls,name,bases,dic) :生了cls这个类对象,里面有东西

    元类中:

    __init__:控制类的产生,在__new__之后

    _call_:对着对象的产生

    __new__:控制类产生最根上,其实本质最根上也不是它,是type的__call__,但是我们控制不了了

    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Person类,Person类中有名称空间之类的了
            # print('xxxxxxx')
            # print(args)
            # print(kwargs)
            # print(name)
            # print(bases)
            # print(dic)
            pass
            # self.name='xxxxxxx'
        def __new__(cls, name,bases,dic):
            # print(name)
            # print(bases)
            # print(dic)
            #产生空对象(空类),在这里面生成的并不是空类,是有数据的类了
            #如何完成类的初始化,并且把name,bases,dic这些东西放入
            # return type.__new__(cls,name,bases,dic)
            dic2={'attr':{}}
            for k,v in dic.items():
                #加入这一句,类名称空间中带__的就不会放到attr中
                if not k.startswith('__'):
                    dic2['attr'][k]=v
            print('-------',dic2)
            return type.__new__(cls,name,bases,dic2)
    
    
    class Person(metaclass=Mymeta):     # Person=Mymeta(name,bases,dic)   调用type的__call__,内部调用了Mymeta.__new__,又掉Mymeta的__init__
        school='音乃木板学院'
        age=10
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
    
    print(Person.__dict__)
    print(Person.attr['school'])
    # p=Person('nick',18)
    

    单例模式

    单例模式是设计模式中的一种,其中一共有23种设计模式

    单例模式:整个过程中只有一个实例,所有生成的实例都指向一块内存空间

    方法一:

    可以通过类的绑定方法来实现:当用户输入端口和地址,实例化产生新对象,当用户不输入端口和地址,每次拿到的对象,都是同一个

    # settings.py
    PORT=3306
    HOST='127.0.0.1'
    
    class Sql():
        _instance=None
        def __init__(self,port,host):
            self.port=port
            self.host=host
        # @classmethod
        # def get_sigoleton(cls):
        #     import settings
        #     if cls._instance:
        #         return cls._instance
        #     else:
        #         cls._instance=cls(settings.PORT,settings.HOST)
        #     return cls._instance
        @classmethod
        def get_sigoleton(cls):
            import settings
            if not cls._instance:
                cls._instance = cls(settings.PORT, settings.HOST)
            return cls._instance
    
    #每次调用get_sigoleton 拿到的对象都是同一个
    s1=Sql.get_sigoleton()
    s2=Sql.get_sigoleton()
    s3=Sql.get_sigoleton()
    
    print(s1)
    print(s2)
    print(s3)
    s4=Sql('33306','192.168.1.1')
    print(s4)
    

    方法二:

    通过装饰器

    def get_sigoleton(cls):
        #cls就是Sql这个类
        import settings
        _instance=cls(settings.PORT, settings.HOST)
        # _instance=Sql(settings.PORT, settings.HOST)
    
        def wrapper(*args,**kwargs):
            if len(args)!=0 or len(kwargs)!=0:
                #表示传了参数,生成新对象
                res=cls(*args,**kwargs)
                return res
            else:
                return _instance
        return wrapper
    
    # def get_sigoleton(cls):
    #     _instance=None
    #     def wrapper(*args,**kwargs):
    #         if len(args)!=0 or len(kwargs)!=0:
    #             #表示传了参数,生成新对象
    #             res=cls(*args,**kwargs)
    #             return res
    #         else:
    #             import settings
    #             nonlocal _instance
    #             if not _instance:
    #                 _instance=cls(settings.PORT, settings.HOST)
    #             return _instance
    #     return wrapper
    
    @get_sigoleton    #会把下面的Sql当中参数传入,相当于:Sql=get_sigoleton(Sql)
    class Sql():
        def __init__(self,port,host):
            self.port=port
            self.host=host
    # Sql=get_sigoleton(Sql)
    s1=Sql()
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    s4=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    

    方法三

    通过元类

    class Mymeta(type):
        def __init__(self,name,bases,dic):
            #self 是Sql类
            import settings
            #把实例化好的对象,放到了类的名称空间
            self._instance=self(settings.PORT, settings.HOST)
        def __call__(self, *args, **kwargs):
            #self是谁?是Sql类
            if len(args)!=0 or len(kwargs)!=0:
                obj=object.__new__(self)
                obj.__init__(*args, **kwargs)
                return obj
            else:
                return self._instance
    
    class Sql(metaclass=Mymeta):    #相当于 Sql=Mymeta(name,bases,dic)   这个会调用 Mymeta的__init__  在里面已经向类的名称空间放了一个对象
        def __init__(self,port,host):
            self.port=port
            self.host=host
    
    print(Sql.__dict__)
    s1=Sql()
    #调用元类的__call__
    s2=Sql()
    s3=Sql('33306','192.168.1.1')
    print(s1)
    print(s2)
    print(s3)
    

    方法四

    利用模块导入(python的模块是天然的单例)

    # sigonleton.py
    
    import settings
    class Sql():
        def __init__(self,port,host):
            self.port=port
            self.host=host
    
    s1=Sql(settings.PORT,settings.HOST)
    
    def test():
        from sigonleton import s1
        print(s1.port)
        print(s1)
    def test2():
        from sigonleton import s1 as s2
        print(s2)
    
    test()
    test2()
    from sigonleton import s1
    from sigonleton import Sql
    s2=Sql(3306,'192.168.1.1')
    print(s1)
    print(s2)
    
  • 相关阅读:
    js固定在顶部
    css垂直居中
    HTML 5离线存储
    jdbc数据库操作
    I/O输入输出流
    异常处理
    java实现冒泡排序算法
    Java 方法
    java 循环 基本类型
    Java中Arrays工具类
  • 原文地址:https://www.cnblogs.com/hyc123/p/11459912.html
Copyright © 2011-2022 走看看