我正在寻找创建单例类的正确方法,该类在第一次创建时就接受参数。 我的研究使我想到了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
__ new __
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
装饰器
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
所有这些都可以正常工作,但是当涉及到初始化时(例如在普通类中使用 __ 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
我不知道这是创建接受参数的单例的正确方法。
答案 0 :(得分:3)
我发现实现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
答案 1 :(得分:1)
除了@AndriyIvaneyko的答案之外,这里还有一个线程安全的元类单例实现:
# Based on tornado.ioloop.IOLoop.instance() approach.
# See https://github.com/facebook/tornado
# Whole idea for this metaclass is taken from: https://stackoverflow.com/a/6798042/2402281
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
希望您发现它有用!
答案 2 :(得分:0)
class OnlyOne:
class __OnlyOne:
def __init__(self, arg):
self.val = arg
def __str__(self):
return repr(self) + self.val
instance = None
def __init__(self, arg):
if not OnlyOne.instance:
OnlyOne.instance = OnlyOne.__OnlyOne(arg)
else:
OnlyOne.instance.val = arg
def __getattr__(self, name):
return getattr(self.instance, name)
用法
x = OnlyOne('sausage')
print(x)
y = OnlyOne('eggs')
print(y)
z = OnlyOne('spam')
print(z)
print(x)
print(y)
print(`x`)
print(`y`)
print(`z`)
output = '''
<__main__.__OnlyOne instance at 0076B7AC>sausage
<__main__.__OnlyOne instance at 0076B7AC>eggs
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.__OnlyOne instance at 0076B7AC>spam
<__main__.OnlyOne instance at 0076C54C>
<__main__.OnlyOne instance at 0076DAAC>
<__main__.OnlyOne instance at 0076AA3C>
'''