Python类:通过传递值来确定是否为Singleton?
我有一个Python3类,它目前是一个使用Python类:通过传递值来确定是否为Singleton?,python,python-3.x,singleton,Python,Python 3.x,Singleton,我有一个Python3类,它目前是一个使用@singleton装饰器定义的单例,但偶尔它需要而不是单例 问题:在实例化类中的对象时,是否可以执行类似于传递参数的操作,并且该参数确定类是否为单例 我试图找到一种替代方法来复制这个类,使它不再是一个单一的类,但这样我们就会有大量的重复代码 Foo.py def singleton(cls): instances={} def getinstance(*args, **kwargs): if cls not in in
@singleton
装饰器定义的单例,但偶尔它需要而不是单例
问题:在实例化类中的对象时,是否可以执行类似于传递参数的操作,并且该参数确定类是否为单例
我试图找到一种替代方法来复制这个类,使它不再是一个单一的类,但这样我们就会有大量的重复代码
Foo.py
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
Class Foo:
def hello(self):
print('hello world!')
Class FooNotSingleton:
def hello(self):
print('hello world!')
from Foo import Foo
from FooNotSingleton import FooNotSingleton
foo = Foo()
foo.hello()
bar = FooNotSingleton()
bar.hello()
footsingleton.py
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
Class Foo:
def hello(self):
print('hello world!')
Class FooNotSingleton:
def hello(self):
print('hello world!')
from Foo import Foo
from FooNotSingleton import FooNotSingleton
foo = Foo()
foo.hello()
bar = FooNotSingleton()
bar.hello()
main.py
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
Class Foo:
def hello(self):
print('hello world!')
Class FooNotSingleton:
def hello(self):
print('hello world!')
from Foo import Foo
from FooNotSingleton import FooNotSingleton
foo = Foo()
foo.hello()
bar = FooNotSingleton()
bar.hello()
您可以基于传递给构造函数的唯一ID构建实例密钥。这样,相同的类和相同的ID将产生相同的实例
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
key = "{}__{}".format(cls, kwargs.get("id"))
if key not in instances:
instances[key] = cls(*args, **kwargs)
return instances[key]
return getinstance
@singleton
class Foo:
def __init__(self, *args, **kwargs):
self.x = 0
def hello(self):
print('My X is:', self.x)
f1 = Foo()
f1.x = 5
f1.hello()
f2 = Foo() # same as f1
f2.hello()
f3 = Foo(id='abc') # new instance, because of new "id" parameter
f3.x = 1024
f3.hello()
f4 = Foo() # same as f1
f4.hello()
输出:
My X is: 5
My X is: 5
My X is: 1024
My X is: 5
可选:在将
id
参数传递给类构造函数之前,您可以从kwargs中删除该参数,而ofc则可以将id
命名为完全不同的东西。我相信这个问题可以通过继承轻松解决FoonNotSingleton
成为包含所有实现细节的基类,Foo
使用@singleton
装饰器从中派生:
footsingleton.py
class FooNotSingleton:
def hello(self):
print('hello world!')
import FooNotSingleton
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class Foo(FooNotSingleton.FooNotSingleton):
pass
from Foo import Foo
from FooNotSingleton import FooNotSingleton
print(id(FooNotSingleton()))
print(id(FooNotSingleton())) # different
print(id(Foo()))
print(id(Foo())) # same
FooNotSingleton().hello() # both works
Foo().hello()
Foo.py
class FooNotSingleton:
def hello(self):
print('hello world!')
import FooNotSingleton
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class Foo(FooNotSingleton.FooNotSingleton):
pass
from Foo import Foo
from FooNotSingleton import FooNotSingleton
print(id(FooNotSingleton()))
print(id(FooNotSingleton())) # different
print(id(Foo()))
print(id(Foo())) # same
FooNotSingleton().hello() # both works
Foo().hello()
main.py
class FooNotSingleton:
def hello(self):
print('hello world!')
import FooNotSingleton
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return getinstance
@singleton
class Foo(FooNotSingleton.FooNotSingleton):
pass
from Foo import Foo
from FooNotSingleton import FooNotSingleton
print(id(FooNotSingleton()))
print(id(FooNotSingleton())) # different
print(id(Foo()))
print(id(Foo())) # same
FooNotSingleton().hello() # both works
Foo().hello()
您可以在带有关键字触发器的
singleton
包装中添加一些额外的处理,以绕过类中带有singleton=False
的非单一实例化:
def singleton(cls):
instances={}
def getinstance(*args, **kwargs):
# thanks to sanyash's suggestion, using a default return instead of try/except
singleton = kwargs.pop('singleton', True)
if singleton:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
else:
return cls(*args, **kwargs)
return getinstance
@singleton
class Foo:
def __init__(self, val):
self.val = val
def hello(self):
print(f'I have value {self.val}')
测试:
需要注意的是,您需要保留一个在任何修饰类中都不可能使用的关键字。好处是只需创建一次类,无需重复。1<代码>\未定义单例。你是说
getinstance
?。2.愚蠢的问题:为什么不删除@singleton
装饰器?@sanyash 1。修正了错误,谢谢!2.我希望同一个类有一个单例版本和一个非单例版本,因此该类的单例版本应该有@singleton
装饰器,而非单例版本不应该。也许我遗漏了一些非常明显的东西?你介意接受一个给定的答案吗?singleton=kwargs.pop('singleton',True)
可以替换try:。。。除了
block。很好的一点是,我们不知道pop()
还有一个默认值,它不会触发键错误
。很高兴知道!