zoukankan      html  css  js  c++  java
  • python的单例模式和__new__方法

    单例模式是一个常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。比如说:利用加标签的白名单防止跨站脚本攻击XXS创建一个XxsFile类,不同的人访问都要创建XxsFile对象的实例,这就导致系统中存在多个XxsFile的实例对象,而这样会严重浪费内存资源。事实上类似于XxsFile这样的类,我们希望在程序运行期间只存在一个实例对象,在python中,我们可以使用单例。如下列几种方法:


    在Python中new方法和init方法类似,但是如果两个都存在那么new先执行

    __new__(cls, *args, **kwargs)

    __new__()中的需要传递一个参数cls,cls表示需要实例化的类,此参数在实例化时由Python解析器自动提供

    1、类方法classmethod

    # -*-coding:utf-8 -*-
    class Foo(object):
        __instance = None
    
        @classmethod
        def instance(self):
            if self.__instance:
                return self.__instance
    
            else:
                obj = self()
                self.__instance = obj
                return self.__instance
    obj1=Foo.instance()
    obj2=Foo.instance()
    print(obj1,obj2)
    

    2、基于__new__方法实现(推荐使用、方便)

    当我们实例化一个对象时,是先执行了类的__new__方法(当我们没写时,默认调用object.__new__),实例化对象;然后再执行类的__init__方法,对这个对象进行初始化,所以我们可以基于这个,实现单例模式:

    # -*-coding:utf-8 -*-
    class Foo(object):
        __instance=None
        def __init__(self):
            pass
        def __new__(cls, *args, **kwargs):
    
            if cls.__instance:
                return cls.__instance
            else:
                obj = object.__new__(cls,*args,**kwargs)
                cls.__instance = obj
                return cls.__instance
    obj1=Foo()
    obj2=Foo()
    print(obj1,obj2)
    

    Python new()方法,为对象分配内存,返回对象的引用

    # -*-coding:utf-8 -*-
    class MusicPlayer(object):
    
        #为对象分配内存空间
        def __new__(cls, *args, **kwargs):
    
            #1、创建对象时,new方法会被自动调用
            print("创建对象,分配内存空间")
    
            #2、为对象分配空间
            instance = super().__new__(cls)
    
            #3、返回对象引用
            return instance
        #对象初始化,定义实例属性
        def __init__(self):
            print("播放器初始化")
    
    #创建播放器对象
    player = MusicPlayer()
    print(player)
    

    __new__方法:

    使用MusicPlayer()创建对象时,python的解释器首先会调用__new__方法为对象分配空间,如果不分配空间那么就不会调用初始化__init____new__是一个由object基类提供的内置的静态方法,主要作用有两个:

    1、在内存空间中为对象分配空间

    2、返回对象的引用

    Python的解释器获取得到对象的引用后,将引用作为第一个参数,传递给__init__,

    1、重写__new__方法python用return super().__new__(cls),否则Python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法,注意:__new__是一个静态方法,在调用时需要主动传递cls参数

    如果分配了内存空间,就会调用初始化__init__的结果:

    # -*-coding:utf-8 -*-
    class MusicPlayer(object):
    
        #为对象分配内存空间
        def __new__(cls, *args, **kwargs):
    
            #1、创建对象时,new方法会被自动调用
            print("创建对象,分配内存空间")
    
            #2、为对象分配空间
            instance = super().__new__(cls)
    
            #3、返回对象引用
            return instance
        #对象初始化,定义实例属性
        def __init__(self):
            print("播放器初始化")
    
    #创建播放器对象
    player = MusicPlayer()
    print(player)
    
    #输出:
        # 创建对象,分配内存空间
        # 播放器初始化
        # <__main__.MusicPlayer object at 0x033D09B0>
    

    如果__new__不分配内存空间,创建对象的时候就不会去的调用__init__,结果如下:

        # -*-coding:utf-8 -*-
    class MusicPlayer(object):
    
        #为对象分配内存空间
        def __new__(cls, *args, **kwargs):
    
            #1、创建对象时,new方法会被自动调用
            print("创建对象,分配内存空间")
    
            
        #对象初始化,定义实例属性
        def __init__(self):
            print("播放器初始化")
    
    #创建播放器对象
    player = MusicPlayer()
    print(player)
    
    #输出:
        #创建对象,分配内存空间
        #None
    
  • 相关阅读:
    Android学习路径(两)项目文件本身使用场景和文件演示
    A左右ndroid正在使用Uri监视数据库中的更改
    离PACKET_INp获取信息acket data
    curl 命令
    POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
    Linux 下一个 Mysql error 2002 错误解决
    图片打水印 缩放 和一个输入流的转换
    qt Qt5开发
    qt 关于Qt中MVC的介绍与使用
    qt mvc3
  • 原文地址:https://www.cnblogs.com/venvive/p/11530684.html
Copyright © 2011-2022 走看看