繁体   English   中英

Python Class: Singleton 或不是 Singleton 通过传递一个值

[英]Python Class: Singleton or Not Singleton by Passing a Value?

I have a Python 3 class that is currently a singleton defined using a @singleton decorator, but occasionally it needs to not be a singleton.

Question: Is it possible to do something similar to passing a parameter when instantiating an object from the class and this parameter determines whether the class is a singleton or not a singleton?

我正在尝试找到一种替代方法来复制 class 并使其不是 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!')

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()

您可以使用关键字触发器在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 而无需重复。

您可以根据传递给构造函数的唯一 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()

Output:

My X is: 5
My X is: 5
My X is: 1024
My X is: 5

可选:您可以在将 kwargs 参数传递给id id为完全不同的名称。

我相信这个问题可以通过 inheritance 轻松解决。 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

主文件

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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM