实现单例的大体思路都是内置一个实例对象作为类的属性,在创建对象时再给实例赋值,或者传递该实例的引用,
Python是通过重写类的__new__方法实现单例,
JAVA实现单例时,会定义一个对外提供获取实例的方法
两者不太一样,需要注意
另外,
python中除了重写__new__方法提供唯一一个实例之外,
如果程序中重写了__init__方法,还要注意修改__init__方法以避免每次重复执行
笔者Python版本为3.7.2,实现单例的代码如下:
class MusicPlay:
# 定义一个实例作为类的属性
instance = None
# 定义一个标记,记录是否执行过初始化动作
init_flag = False
def __new__(cls, *args, **kwargs):
""" 创建对象时,new方法会被自动调用"""
# super 与 super()
# print(super, type(super),super.__class__.__name__)
# print(super(), type(super()),super().__class__.__name__)
# print(super is super())
# print()
# print(super.__doc__)
# print()
# print(super().__doc__)
# print()
# 判断类属性是否被实例化(初始化)
if cls.instance is None:
print("实例对象分配空间...")
# 调用父类方法,为对象分配空间
cls.instance = super().__new__(cls)
# 返回类属性实例的引用
return cls.instance
# 也可以简写成
# return super().__new__(cls)
def __init__(self):
# 初始化动作只执行一次
# 如果执行过,直接返回
if MusicPlay.init_flag:
return
print("实例对象初始化...")
MusicPlay.init_flag = True
music_play1 = MusicPlay()
music_play2 = MusicPlay()
print("music_play1 is music_play2:", music_play1 is music_play2)
print(music_play1)
print(music_play2)
结果如下:
实例对象分配空间...
实例对象初始化...
music_play1 is music_play2: True
<__main__.MusicPlay object at 0x0000000002139A90>
<__main__.MusicPlay object at 0x0000000002139A90>
网上也有关于Python2实现单例,稍有不同
class A(object):
#用类属性用来标识是否是第一次创建对象
__ins = None
def __new__(cls):
#如果是第一次创建对象就把该对象的引用保存到__ins内
if cls.__ins == None:
cls.__ins = object.__new__(cls)
#返回第一次创建对象的引用
return cls.__ins
else:
#返回上一次创建的对象的引用
return cls.__ins
a = A()
b = A()
print (id(a))
print (id(b))
执行结果
18991816
18991816