【问题标题】:Which usage of singleton is the most proper/pythonic?单例的哪种用法最合适/pythonic?
【发布时间】:2021-09-20 13:39:32
【问题描述】:

我想知道哪种方式是调用单例变量的最佳、最合适或最 Pythonic。

这是我的单例代码:

class SingletonMeta(type):
    _instances = {}

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


class Singleton(metaclass=SingletonMeta):
    @classmethod
    def set_value(cls, key, value):
        setattr(cls, key, value)

        return value

    @classmethod
    def get_value(cls, key):
        return getattr(cls, key)

我的第一个方法是这样的:

Singleton.set_value('my_value', True)
print(Singleton.get_value('my_value'))

但对我来说它看起来有点“丑陋”。

所以我将 Singleton 类更改为简单的 pass 然后我可以这样做:

Singleton.my_value = True
print(Singleton.my_value)

为了让 PyC​​harm 平静下来,我添加了 Singletonmy_value = None

我想知道,这些方法中哪种方法最好?或者也许我应该以不同的方式来处理它?

【问题讨论】:

    标签: python singleton


    【解决方案1】:

    第二种方法最好,但是...

    您创建的 SingletonMeta 执行您希望它执行的操作,因为它确保您不能创建多个 Singleton 类的实例。它通过确保每次调用 Singleton() 时都返回相同的实例来实现这一点。所以

    >>> a = Singleton()
    >>> b = Singleton()
    >>> a is b
    True
    

    解决了这个问题,现在可以了:

    >>> a.my_value = True
    >>> b.my_value
    True
    

    您可以像在实例上一样轻松地在类上创建属性这一事实与 Python 课程非常相似。如果您在类上创建一个属性,则它由所有实例“共享”,如果您在一个实例上创建它,则它特定于该实例。由于 Singleton 的实例只有一个,因此不清楚为什么要创建/更改 Singleton 类本身的属性,而不是实例。可以说,最 Pythonic 的方式是为实例 Singleton() 上的属性赋值,而不是 Singleton 本身

    【讨论】:

    • 嗯,我没想到这个。所以你是说,我想在我的单例中访问数据的任何地方我都应该做类似my_singleton = Singleton() 然后my_singleton.my_value = True 并且我应该在我想访问这个my_value 的每个类中这样做是正确的吗?因为这样我会在任何地方都使用实例,而不是类本身,对吧?
    • 这取决于您对单例模式的特定用例。您展示的 SingletonMeta 是 Singleton 模式的许多可能实现之一。您将使用此特定实现来隐藏 Singleton 类的不同实例实际上是同一个对象的事实。仅当您有不同的实例时,这才有意义。如果您只想更改全局对象的属性,请创建该全局对象。无需为此使用(实例)单例元类。
    • 我的用例是为我的应用程序存储“设置”。我的程序中有许多类和模块,我需要一种方法来动态地响应在不同地点和时刻发生的不同设置的变化。这就是我决定单例的原因。目前我想知道是否只使用Singleton.my_value = True 而不是my_singleton = Singleton()my_singleton.my_value = True 是否会被视为错误?
    • 设置本质上是全局的,因此可以将设置放在设置模块中的全局变量中。即使您在程序的不同部分导入该模块,它也将始终是同一个模块,因此,其命名空间中的相同全局对象。正是您正在寻找的那种单身行为,
    • 谢谢。我又做了一个小改动,我就是这样做的 - Settings().my_value = True。您如何看待这样的方法?我认为这也很好,因为我实际上在这里使用的是单例(而不是类变量),我不需要创建一个类实例和代码的开头,因为我可以在任何地方使用Settings(),因为我使用的是单例。你怎么看?
    猜你喜欢
    • 2020-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 2016-11-19
    • 2018-10-17
    相关资源
    最近更新 更多