Python Class:单例还是非单例传递值?
Python Class: Singleton or Not Singleton by Passing a Value?
我有一个 Python 3 class 目前是使用 @singleton
装饰器定义的单例,但偶尔它需要 而不是 单身。
问题:在class实例化一个对象时,是否可以做类似传递参数的事情,这个参数决定是否class是单例还是非单例?
我正在尝试找到一种替代方法来复制 class 并使它不是单例,但那样我们就会有大量重复的代码。
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!')
FooNotSingleton.py
Class FooNotSingleton:
def hello(self):
print('hello world!')
main.py
from Foo import Foo
from FooNotSingleton import FooNotSingleton
foo = Foo()
foo.hello()
bar = FooNotSingleton()
bar.hello()
您可以根据传递给构造函数的唯一 ID 构建实例密钥。这样,相同的 class 和 相同的 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
参数传递给 class 构造函数之前从 kwargs 中删除它 - 当然您可以命名 id
完全不同的东西。
我相信这个问题可以通过继承轻松解决。 FooNotSingleton
成为具有所有实现细节的基础 class,并且 Foo
使用 @singleton
装饰器从中派生:
FooNotSingleton.py
class FooNotSingleton:
def hello(self):
print('hello world!')
Foo.py
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
main.py
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
包装器中使用关键字触发器添加一些额外的处理,以绕过 class:
中带有 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}')
测试:
s1 = Foo('single')
s2 = Foo('another single')
ns = Foo('not single', singleton=False)
s1.hello()
# I have value single
s2.hello()
# I have value single
ns.hello()
# I have value not single
需要注意的是,您需要保留一个不太可能用于任何修饰 class 的关键字。好处是您只需要创建一次 class 而不会重复。
我有一个 Python 3 class 目前是使用 @singleton
装饰器定义的单例,但偶尔它需要 而不是 单身。
问题:在class实例化一个对象时,是否可以做类似传递参数的事情,这个参数决定是否class是单例还是非单例?
我正在尝试找到一种替代方法来复制 class 并使它不是单例,但那样我们就会有大量重复的代码。
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!')
FooNotSingleton.py
Class FooNotSingleton:
def hello(self):
print('hello world!')
main.py
from Foo import Foo
from FooNotSingleton import FooNotSingleton
foo = Foo()
foo.hello()
bar = FooNotSingleton()
bar.hello()
您可以根据传递给构造函数的唯一 ID 构建实例密钥。这样,相同的 class 和 相同的 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
参数传递给 class 构造函数之前从 kwargs 中删除它 - 当然您可以命名 id
完全不同的东西。
我相信这个问题可以通过继承轻松解决。 FooNotSingleton
成为具有所有实现细节的基础 class,并且 Foo
使用 @singleton
装饰器从中派生:
FooNotSingleton.py
class FooNotSingleton:
def hello(self):
print('hello world!')
Foo.py
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
main.py
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
包装器中使用关键字触发器添加一些额外的处理,以绕过 class:
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}')
测试:
s1 = Foo('single')
s2 = Foo('another single')
ns = Foo('not single', singleton=False)
s1.hello()
# I have value single
s2.hello()
# I have value single
ns.hello()
# I have value not single
需要注意的是,您需要保留一个不太可能用于任何修饰 class 的关键字。好处是您只需要创建一次 class 而不会重复。