python实现单例与new()方法
new 和 init 方法
- _ new _ 方法进行分配空间
- _ init _ 对象初始化
在利用init方法实例化对象会首先使用new方法创建一个空间,即一个内存地址。
new() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
class B:
def __init__(self):
print("init")
def __new__(cls, *args, **kwargs):
print("new")
return object.__new__(cls)
a = B()
执行结果:
new
init
所以比较容易看出,首先执行的时new方法,然后执行init;
需要单例的原因
在对一个类对象进行实例化时,可以实例化出很多不同对象。每一次实例化出的对象,内存中需要重新分配一个地址,因此会造成空间浪费。而且在类似于线程池时,需要实现同步,不发生冲突,也需要在同一块数据空间操作。还有类似于windows中垃圾桶操作。
例:
class A:
pass
a = A()
print('a对象所在的内存地址是 %d, A类所在的内存地址是 %d' % (id(a), id(A)))
b = A()
print('b对象所在的内存地址是 %d, A类所在的内存地址是 %d' % (id(b), id(A)))
c = A()
print('c对象所在的内存地址是 %d, A类所在的内存地址是 %d' % (id(c), id(A)))
输出:
a对象所在的内存地址是 1343886076112, A类所在的内存地址是 1343831237640
b对象所在的内存地址是 1343886085592, A类所在的内存地址是 1343831237640
c对象所在的内存地址是 1343886076280, A类所在的内存地址是 1343831237640
python实现单例
instance变量名中“_” 代表着类的私有变量;
class A:
_instance = None
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
#此处去掉对于是否初次实例化_instance值的判断
cls._instance = object.__new__(cls)
return cls._instance
b = A('one', 1)
print(b)
c = A('two', 2)
print(c)
输出:
<__main__.A object at 0x00000138E5DC29E8>
<__main__.A object at 0x00000138E5DC2BE0>
通过python实现单例,通过_instance(bool型)值的判定,决定是否再次分配新的数据空间。
class A:
_instance = None
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls)
return cls._instance
b = A('one', 1)
print(b)
c = A('two', 2)
print(c)
输出:
<__main__.A object at 0x00000138E5DC2D30>
<__main__.A object at 0x00000138E5DC2D30>
不难发现,空间地址是没有发生变化的,实现了单例;