Lolizeppelin's Blog

python 单例模式

Posted on By gcy

neutron的代码里比较喜欢如下单例模式实现

class Plugin(db.AutoAllocatedTopologyMixin):

    _instance = None

    supported_extension_aliases = ["auto-allocated-topology"]

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    def get_plugin_description(self):
        return "Auto Allocated Topology - aka get me a network."

    def get_plugin_type(self):
        return "auto-allocated-topology"

#获取单例
plugin = Plugin.get_instance()

nova里的单例launcher写法

def launch(conf, service, workers=1):
    ...
    if workers is None or workers == 1:
        launcher = ServiceLauncher(conf)
        launcher.launch_service(service)
    else:
        launcher = ProcessLauncher(conf)
        launcher.launch_service(service, workers=workers)
    return launcher

_launcher = None

def serve(server, workers=None):
    global _launcher
    if _launcher:
        raise RuntimeError(_('serve() can only be called once'))
    _launcher = service.launch(CONF, server, workers=workers)

再来一个new的写法

class Singleton(object):

    # 定义静态变量实例
    __instance = None

    def __init__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls.__instance

instance1 = Singleton()

线程安全写法

Lock = threading.Lock()

class Singleton(object):
    __instance = None

    def __init__(self):
        pass

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            try:
                Lock.acquire()
                # 通过线程锁做双重检查
                if not cls.__instance:
                    cls._instance = cls()
            finally:
                Lock.release()                
        return cls._instance

python流行协程,所以现在都不关心线程安全了

其实最简单的单例模式方式

文件singleton.py

class Singleton(object):
    __instance = None
    def __init__(self):
        pass
    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()              
        return cls._instance

singleton = Singleton.get_instance()

文件main.py

import singleton
intance = singleton.singleton

上述写法就是第一次import就初始化好了实例,不用考虑线程安全

因为python中的module就是最好的单例模式

写在最末尾,了解单例模式可以更好的理解pthon中一切皆对象,module里的class、function其实都是对象,而且都是单例的

最近发现openstack里一个厉害的单例写法,通过元类达成

# 继承type实现单例
class Singleton(type):
    _instances = {}
    _semaphores = lockutils.Semaphores()

    def __call__(cls, *args, **kwargs):
        # lock可以用thread的lock做
        with lockutils.lock('singleton_lock', semaphores=cls._semaphores):
            if cls not in cls._instances:
                cls._instances[cls] = super(Singleton, cls).__call__(
                    *args, **kwargs)
        return cls._instances[cls]

# 添加metaclass的闭包
def add_metaclass(metaclass):
    """Class decorator for creating a class with a metaclass."""
    def wrapper(cls):
        orig_vars = cls.__dict__.copy()
        orig_vars.pop('__dict__', None)
        orig_vars.pop('__weakref__', None)
        for slots_var in orig_vars.get('__slots__', ()):
            orig_vars.pop(slots_var)
        return metaclass(cls.__name__, cls.__bases__, orig_vars)
    return wrapper

@add_metaclass(Singleton)
class YourClass(object):
    """docstring for ."""
    def __init__(self, arg):
        super(, self).__init__()
        self.arg = arg