汇总Python实现单例模式的四大方式

之前Django开发使用过集中单例模式,今天来整理下这些实现单例模式的方式。

法一:使用__new__魔法方法

1
2
3
4
5
class SingleMode1:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance

说明:使用__new__方法对实例进行增强!

测试及结果:

1
2
3
m1 = SingleMode1()
m2 = SingleMode1()
print(hash(m1) == hash(m2)) # True

法二:使用自定义装饰器实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


def single(cls):
_instance = {}

def generate_obj(*args, **kwargs):
if _instance.setdefault(cls,None):
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]

return generate_obj


@single
class SingleMode4:
pass

测试及结果:

1
2
3
m5 = SingleMode4()
m6 = SingleMode4()
print(hash(m5) == hash(m6)) # True

说明:其核心思想是利用类属性(这里用了字典类型)来判断实例是否已被创建过一次!


法三:使用@classmethod类装饰器实现

1
2
3
4
5
6
7
8
class SingleMode2:
_instance = None

@classmethod
def create_obj(cls, *args, **kwargs):
if not getattr(cls, '_instance'):
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance

说明:其核心思想是利用类属性来判断实例是否已被创建过一次!

测试及结果:

1
2
3
m3 = SingleMode2.create_obj()
m4 = SingleMode2.create_obj()
print(hash(m3) == hash(m4)) # True

法三:Python的模块导入

1
2
3
4
5
6
# celery.py
from django.conf import settings

# __init__.py
settings = LazySettings()

注:使用懒加载的方式将配置文件动态放入到内存中执行,同时在内存中只需创建一份实例,全局都会使用这一份实例,不会再去创建新的实例。

结论:

单例模式的存在,是为了应对在某项业务在大量请求的情况下,需要创建大量的实例而出现的,单例模式大大降低创建大量实例消耗的内存资源。

Python使用单例的核心思想就是在创建实例前,判断类中是否已经存在保存该实例的类属性!