我正在寻找正确的方法来创建在第一次创建中接受参数的单例类。我的研究将我引向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)
我不知道这是否是创建接受参数的单例的正确方法。
我发现实现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)
除了@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)
希望你觉得它有用!
| 归档时间: |
|
| 查看次数: |
1254 次 |
| 最近记录: |