在python中,我们可以使用多种方法来实现单例:
1,使用模块
2,使用__new__
3,使用装饰器
4,使用元类(metaclass)
1,使用模块:python的模块就是天然的单例模式,模块进行歹意吃导入时会生成.pyc文件,第二次导入时直接加载,不会再次执行模块代码,因此我们把模块单独定义在一个模块中,就可以获得一个单例了
#Single.py文件
class MySingle:
def f(self):
print('模块单例方式')
s = MySingle()
将上述代码保存在Single.py文件中 在其他文件中进行导入
from Single import s
s.f()
#模块单例方式
2,使用__new__: 为了类只有一个实例,我们可以使用__new__方法来控制创建实例的方法
__init__:初始化方法, 先执行 __new__:创建单例
class Info(object):
str=None
def __new__(cls, *args, **kwargs):
if cls.str==None: # 如果他是空,就重写 重新赋值 给他新的内存空间 其他在来就都是None
cls.str=super().__new__(cls)
return cls.str
def __init__(self): # init方法先执行
print('init方法')
str1=Info() # 单例模式就是只能生成唯一一个对象,
str2=Info()
print('str1: %s'%str1)
print('str2:%s'%str2)
#init方法
str1: <__main__.Info object at 0x00000248A2E5A908>
str2:None
new方法每次实例化的时候都之后一个实例对象:
class A(object):
_intance=None
def __new__(cls, *args, **kwargs):
if cls._intance==None:
cls._intance=object.__new__(cls)
return cls._intance
else:
return cls._intance # 如果他不为空 就返回该对象
a=A()
b=A()
print('a:%s'%a)
print('b:%s'%b)
a:<__main__.A object at 0x000001E42ABEA940>
b:<__main__.A object at 0x000001E42ABEA940>
3,试用装饰器可以动态的修改一个类和函数的功能,或者装饰某个类,用来只生成一个实例对象。
# 使用装饰器
def singleton(cls):
instances={}
def getinstance(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return getinstance
@singleton
class MyClass:
print('MyClass')
c1=MyClass()
c2=MyClass()
print(c1==c2)
# MyClass
# True
4,使用元类(metaclass):元类可以控制类的创建过程,是他创建三件事:
1,拦截类的创建
2,修改类的定义
3,返回修改的类
# 使用元类
class Singleton2(type):
def __init__(self,*args,**kwargs): #初始化数据
self._instance=None
super(Singleton2,self).__init__(*args,**kwargs)
def __call__(self, *args, **kwargs):
if self._instance is None:
self._instance=super(Singleton2,self).__call__(*args,**kwargs)
return self._instance
class F(metaclass=Singleton2): #python2中的写法是class F(objects):
__metaclass__ = Singleton2 # 代码在执行到这里的时候其实已经执行了__init__方法和__call__方法,而不是在执行F实例化是才执行,而且只执行一次
f1 = F()
f2 = F()
print(F.__dict__)
print(f1 is f2)
"""
{'__module__': '__main__', '__metaclass__': <class '__main__.Singleton2'>, '__dict__': <attribute '__dict__' of 'F' objects>, '__weakref__': <attribute '__weakref__' of 'F' objects>, '__doc__': None, '_instance': <__main__.F object at 0x00000215B2A0A940>}
True
此时 '_instance': <__main__.F object at 0x00000215B2A0A940>} 存在一个私有属性来保存属性,而不会污染F类(其实还是会污染,不过是使用_instance属性访问)
"""