Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python类:通过传递值来确定是否为Singleton?_Python_Python 3.x_Singleton - Fatal编程技术网

Python类:通过传递值来确定是否为Singleton?

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

我有一个Python3类,它目前是一个使用
@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()
还有一个默认值,它不会触发
键错误
。很高兴知道!