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