首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python类: Singleton还是非Singleton,通过传递值?

Python类: Singleton还是非Singleton,通过传递值?
EN

Stack Overflow用户
提问于 2019-10-08 13:48:23
回答 3查看 250关注 0票数 2

我有一个Python3类,它目前是一个使用@singleton装饰器定义的单例类,但有时它需要而不是

问题:当从类实例化对象时,是否可以执行类似于传递参数的操作,而这个参数决定类是单例还是非单例?

我正在试图找到一种替代方法来复制类,使其不再是单例,但是这样我们就会有大量的重复代码。

Foo.py

代码语言:javascript
复制
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

代码语言:javascript
复制
Class FooNotSingleton:
    def hello(self):
        print('hello world!')

main.py

代码语言:javascript
复制
from Foo import Foo
from FooNotSingleton import FooNotSingleton

foo = Foo()
foo.hello()

bar = FooNotSingleton()
bar.hello()
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-10-08 14:34:13

您可以使用关键字触发器在singleton包装器中添加一些额外的处理,以绕过类中使用singleton=False的非单个实例化:

代码语言:javascript
复制
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}')

测试:

代码语言:javascript
复制
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

请注意,您需要保留一个不太可能在任何修饰类中使用的关键字。好处是您只需要创建类一次,而不需要重复。

票数 1
EN

Stack Overflow用户

发布于 2019-10-08 14:01:53

可以根据传递给构造函数的唯一ID生成实例键。这样,相同的类--相同的ID --将产生相同的实例。

代码语言:javascript
复制
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()

输出:

代码语言:javascript
复制
My X is: 5
My X is: 5
My X is: 1024
My X is: 5

可选:在将id参数传递给类构造函数之前,可以从kwargs中删除它--并且可以将id命名为完全不同的东西。

票数 0
EN

Stack Overflow用户

发布于 2019-10-08 14:07:10

我相信这个问题可以很容易地通过继承解决。FooNotSingleton成为一个包含所有实现细节的基类,Foo通过使用@singleton装饰器从它派生:

FooNotSingleton.py

代码语言:javascript
复制
class FooNotSingleton:
    def hello(self):
        print('hello world!')

Foo.py

代码语言:javascript
复制
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

代码语言:javascript
复制
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()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58287723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档