如何在python中使用参数创建单例类

sha*_*dow 3 python python-3.x

我正在寻找正确的方法来创建在第一次创建中接受参数的单例类。我的研究将我引向3种不同的方式:

元类

class Singleton(type):
    instance = None
    def __call__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance

class ASingleton(metaclass=Singleton):
    pass
Run Code Online (Sandbox Code Playgroud)

__新__

class Singleton(object):
    instance = None
    def __new__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super().__new__(cls, *args, **kwargs)
        return cls.instance
Run Code Online (Sandbox Code Playgroud)

装饰器

def Singleton(myClass):
    instances={}
    def getInstance(*args, **kwargs):
        if myClass not in instances:
            instances[myClass] = myClass(*args, **kwargs)
        return instances[myClass]
    return getInstance

@Singleton
class SingletonTest(object):
    pass
Run Code Online (Sandbox Code Playgroud)

所有这些都可以正常工作,但是当涉及到初始化时(例如在普通类中使用__init__),我无法找出实现它的正确方法。我能想到的唯一解决方案是以这种方式使用metaclass方法:

class Singleton(type):
    instance = None

    def __call__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls.instance

class ASingleton(metaclass=Singleton):
    def __init__(self,j):
        self.j=j
Run Code Online (Sandbox Code Playgroud)

我不知道这是否是创建接受参数的单例的正确方法。

And*_*yko 5

我发现实现Singleton的最佳方法是使用元类:

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]

# Python 2
class MyClass():
    __metaclass__= Singleton

# Python 3
class MyClass(metaclass=Singleton):
     pass
Run Code Online (Sandbox Code Playgroud)


Tho*_*sse 5

除了@AndriyIvaneyko 的答案之外,这里还有一个线程安全的元类单例实现:

# Based on tornado.ioloop.IOLoop.instance() approach.
# See https://github.com/facebook/tornado
# Whole idea for this metaclass is taken from: /sf/answers/475862971/
import threading

class ThreadSafeSingleton(type):
    _instances = {}
    _singleton_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        # double-checked locking pattern (https://en.wikipedia.org/wiki/Double-checked_locking)
        if cls not in cls._instances:
            with cls._singleton_lock:
                if cls not in cls._instances:
                    cls._instances[cls] = super(ThreadSafeSingleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class YourImplementation(metaclass=ThreadSafeSingleton):
    def __init__(self, *args, **kwargs):
        pass  # your implementation goes here
Run Code Online (Sandbox Code Playgroud)

希望你觉得它有用!