如何使 Python 单例类实例化在多个模块之间保持一致?

问题描述 投票:0回答:2

我有一个实现标准单例设计模式的类

ServerController
。每当该类在其起源的同一文件中实例化时 (
main.py
),它都会按预期运行,并使用
ServerController
对象的第一个实例。但是,当我从另一个包含
get_ctrl()
的模块调用类的 getter 函数
main.py
时,尽管我采用单例设计模式,但仍会创建一个新实例。

这是我的单例实现:

class ServerController():
    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super().__new__(cls)
            print("creating ctrl instance", cls.__instance)
        return cls.__instance

    pass

这是班级的

get_ctrl()
吸气功能:

    @classmethod
    def get_ctrl(cls):
        if cls.__instance is None:
            cls.__instance = ServerController()
        return cls.__instance

在我的其他模块中,我调用

from main import ServerController
然后是

ctrl = ServerController.get_ctrl().

解决方案尝试1:

我也尝试过 functools 方法 但没有成功:

@classmethod
@functools.cache
def get_ctrl(): 
    return ServerController()

解决方案尝试2:

除了上面显示的内容外,我还尝试了一个有点不同的

get_ctrl()
的实现:

    @SingletonCache
    @classmethod
    def get_ctrl(cls):
        return cls()

这伴随着

SingletonCache
课:

class SingletonCache:
    def __init__(self, func):
        self.func = func
        self.cache = {}

    def __call__(self, cls):
        if cls not in self.cache:
            self.cache[cls] = self.func(cls)
        return self.cache[cls]

这个方法给我读取的类型错误,

SingletonCache.__call__() missing 1 required positional argument: 'cls'

我也尝试过将

@classmethod
装饰器添加到
__call__(self, cls)
但没有成功。我愿意尝试任何允许我跨多个模块使用单个
ServerController
对象的方法。

感谢任何帮助。谢谢

python oop design-patterns singleton
2个回答
0
投票

对于

singleton pattern
,我认为最好的方法是使用
metaclass
。 试试这个:

class SingletonMeta(type):

    __instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls.__instances:
            cls.__instances[cls] = super().__call__(*args, **kwargs)
        return cls.__instances[cls]


class ServerController(metaclass=SingletonMeta):

    @classmethod
    def get_ctrl(cls, *args, **kwargs):
        return cls(*args, **kwargs)


s1 = ServerController()
s2 = ServerController.get_ctrl()
print(s1)
print(s2)
print(s1 == s2)
<__main__.ServerController object at 0x00000269013ACD00>
<__main__.ServerController object at 0x00000269013ACD00>
True

0
投票

几分钟前,我正在尝试实现一种简单的方法来制作单例类,与类定义互补,而无需创建子类。覆盖

__new__
方法并为其创建一些内部符号。你可以在这里找到一个函数式方法.

© www.soinside.com 2019 - 2024. All rights reserved.