python interest in single mode
Usage scenarios:
+ Python's logger is a singleton for logging
+ Windows Explorer is a singleton
+ thread pools, database connection pools resource pool generally use a singleton
+ website counter
From these usage scenarios we can summarize singleton needs under what circumstances:
1. 当每个实例都会占用资源,而且实例初始化会影响性能,这个时候就可以考虑使用单例模式,它给我们带来的好处是只有一个实例占用资源,并且只需初始化一次;
2. 当有同步需要的时候,可以通过一个实例来进行同步控制,比如对某个共享文件(如日志文件)的控制,对计数器的同步控制等,这种情况下由于只有一个实例,所以不用担心同步问题。
- __new__ way to achieve
class Singleton(object):
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
# 可以在这里给实力对象绑定一些固有属性
# cls.__instance.appkey = ""
return cls.__instance
- 1.1
class Singleton(object):
def __new__(cls, *args, **kwargs):
# 判断是否存在类属性_instance,_instance是类CCP的唯一对象,即单例
if not hasattr(Singleton, "__instance"):
cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
# cls.__instance = object.__new__(cls)
return cls.__instance
However, the above methods have multiple threads thread-safety issues, when there are multiple threads to initialize the object, it is possible to simultaneously determine __instance is None, to enter the instance initialization code (if there is __init__ method) . It is necessary to use a mutex to solve this problem.
- Implement a thread-safe singleton
import threading
try:
from synchronize import make_synchronized
except ImportError:
def make_synchronized(func):
import threading
func.__lock__ = threading.Lock()
# 用装饰器实现同步锁
def synced_func(*args, **kwargs):
with func.__lock__:
return func(*args, **kwargs)
return synced_func
class Singleton(object):
__instance = None
@make_synchronized
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self):
self.blog = "blog"
# -------------
def worker():
e = Singleton()
print(id(e))
def meta():
e1 = Singleton()
e2 = Singleton()
e1.blog = 123
print(e1.blog)
print(e2.blog)
print(id(e1))
print(id(e2))
if __name__ == "__main__":
meta()
tasks = [threading.Thread(target=worker) for _ in range(20)]
for task in tasks:
task.start()
task.join()
- Decorator singleton object to obtain
# 装饰器(decorator)可以动态地修改一个类或函数的功能
import functools
def singleton(cls):
__instance = {}
@functools.wraps(cls)
def getinstance(*args, **kwargs):
if cls not in __instance:
__instance[cls] = cls(*args, **kwargs)
return __instance[cls]
return getinstance
@singleton
class MyClass(object):
a = 1
We define a decorator singleton, it returns an internal function getinstance, the function will determine whether or not a class in the dictionary instances, if not present, it will be cls as a key, cls (* args, ** kw) as value stored in the instances, or directly back instances [cls].
- Use metaclass metaclass to create a singleton
metaclass (metaclass) can control the process of creating the class, it is mainly to do three things:- Creating interception class
- Modify the definition of the class
- Returns the modified class
class Singleton(type):
__instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls.__instances:)
cls.__instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls.__instances[cls]
# python2写法
# class MyClass(object):
# __metaclass__ = Singleton()
# python3写法
class MyClass(metaclass=Singleton):
def __init__(self):
self.blog = "blog"
Reference:
the Python is a singleton
design pattern (Python) - Singleton