Maison  >  Article  >  développement back-end  >  Quelles sont les manières courantes d’implémenter le modèle singleton en Python ?

Quelles sont les manières courantes d’implémenter le modèle singleton en Python ?

WBOY
WBOYavant
2023-05-12 09:07:171036parcourir

Plusieurs façons courantes d'implémenter le modèle singleton en Python

Métaclasse :

class SingletonType(type):
    """
    单例元类。用于将普通类转换为单例类。
    """
    _instances = {}  # 存储单例实例的字典
    def __call__(cls, *args, **kwargs):
        """
        重写 __call__ 方法。用于创建和返回单例实例。
        """
        if cls not in cls._instances:  # 如果类还没有实例化过
            cls._instances[cls] = super().__call__(*args, **kwargs)  # 则创建新实例并存储在字典中
        return cls._instances[cls]  # 返回字典中的实例
class MyClass(metaclass=SingletonType):
    """
    单例类。使用元类 SingletonType 将其转换为单例类。
    """
    def __init__(self, name):
        self.name = name
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")
# 创建 MyClass 的两个实例,应该是同一个对象
obj1 = MyClass("Alice")
obj2 = MyClass("Bob")
# 打印两个实例的内存地址,应该相同
print(hex(id(obj1)))  # 输出:0x7f8d94547a90
print(hex(id(obj2)))  # 输出:0x7f8d94547a90
# 调用两个实例的方法,输出应该相同
obj1.say_hello()  # 输出:Hello, my name is Alice.
obj2.say_hello()  # 输出:Hello, my name is Alice.

Dans le code ci-dessus, nous définissons une métaclasse nommée SingletonType et l'attribuons Utilisé comme métaclasse pour MyClass code>. Dans la classe <code>SingletonType, nous maintenons un dictionnaire _instances qui stocke des instances uniques de chaque classe. Dans la méthode __call__(), nous vérifions le dictionnaire _instances et si la classe n'a pas déjà d'instance, créons une nouvelle instance et l'ajoutons à _instances. Enfin, nous renvoyons les instances dans <code>_instances. SingletonType 的元类,并将其用作 MyClass 的元类。在 SingletonType 类中,我们维护了一个 _instances 字典,用于存储每个类的唯一实例。在 __call__() 方法中,我们检查 _instances 字典,如果类尚未拥有实例,则创建一个新实例并添加到 _instances 中。最后,我们返回 _instances 中的实例。

MyClass 类中,我们定义了一个带参数的构造函数,并且使用 metaclass 参数来指定 SingletonType 元类。由于 MyClass 类使用 SingletonType 元类,因此它具有单例行为。在程序中,我们创建了 MyClass 的两个实例 obj1obj2,然后打印它们的内存地址以验证它们是否是同一个对象。最后,我们调用这两个实例的方法,输出应该相同。

装饰器(Decorator):

def singleton(cls):
    """
    单例装饰器。用于将普通类转换为单例类。
    """
    instances = {}  # 存储单例实例的字典
    def get_instance(*args, **kwargs):
        """
        获取单例实例的方法。
        """
        if cls not in instances:  # 如果类还没有实例化过
            instances[cls] = cls(*args, **kwargs)  # 则创建新实例并存储在字典中
        return instances[cls]  # 返回字典中的实例
    return get_instance
@singleton
class MyClass:
    """
    单例类。使用装饰器 singleton 将其转换为单例类。
    """
    def __init__(self, name):
        self.name = name
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")
# 创建 MyClass 的两个实例,应该是同一个对象
obj1 = MyClass("Alice")
obj2 = MyClass("Bob")
# 打印两个实例的内存地址,应该相同
print(hex(id(obj1)))  # 输出:0x7f8d94547a90
print(hex(id(obj2)))  # 输出:0x7f8d94547

在上面的代码中,我们定义了一个名为 singleton 的装饰器函数。在 singleton 函数内部,我们创建了一个 instances 字典,用于存储每个类的唯一实例。然后,我们定义了一个名为 get_instance 的内部函数,用于获取单例实例。在 get_instance 函数中,我们检查 instances 字典,如果类尚未拥有实例,则创建一个新实例并添加到 instances 中。最后,我们返回字典中的实例。

MyClass 类上应用 @singleton 装饰器,以将其转换为单例类。由于该装饰器是针对类进行操作的,因此它可以轻松地将任何普通类转换为单例类。在程序中,我们创建了 MyClass 的两个实例 obj1obj2,然后打印它们的内存地址以验证它们是否是同一个对象。最后,我们调用这两个实例的方法,输出应该相同。

模块(Module):

# mymodule.py
class MyClass:
    """
    单例类。
    """
    def __init__(self, name):
        self.name = name
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")
my_singleton = MyClass("Alice")  # 创建单例实例
# main.py
from mymodule import my_singleton
# 使用单例实例
my_singleton.say_hello()  # 输出:Hello, my name is Alice.

在上面的代码中,我们将 MyClass 类定义在一个独立的模块 mymodule.py 中,并在其中创建了一个单例实例 my_singleton。然后,在另一个文件 main.py 中,我们从 mymodule 模块中导入 my_singleton 实例,并使用它来调用 say_hello() 方法。

由于 Python 模块在首次导入时会自动执行,因此我们可以利用这一特性来创建单例实例。在 mymodule.py 模块中,我们可以确保 my_singleton 只会被创建一次,并在程序的其他部分中共享它。

new 方法:

class MyClass:
    """
    单例类。
    """
    _instance = None  # 存储单例实例的类变量
    def __new__(cls, *args, **kwargs):
        """
        重写 __new__ 方法。用于创建和返回单例实例。
        """
        if cls._instance is None:  # 如果类还没有实例化过
            cls._instance = super().__new__(cls)  # 则创建新实例并存储在类变量中
        return cls._instance  # 返回类变量中的实例
    def __init__(self, name):
        self.name = name
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")
# 创建 MyClass 的两个实例,应该是同一个对象
obj1 = MyClass("Alice")
obj2 = MyClass("Bob")
# 打印两个实例的内存地址,应该相同
print(hex(id(obj1)))  # 输出:0x7f8d94547a90
print(hex(id(obj2)))  # 输出:0x7f8d94547a90
# 调用两个实例的方法,输出应该相同
obj1.say_hello()  # 输出:Hello, my name is Alice.
obj2.say_hello()  # 输出:Hello, my name is Alice.

在上面的代码中,我们将 MyClass 类的构造函数改为 __new__() 方法,并使用 _instance 类变量来存储单例实例。在 __new__() 方法中,我们检查 _instance 变量,如果类尚未拥有实例,则创建一个新实例并添加到 _instance 中。最后,我们返回 _instance 中的实例。

在程序中,我们创建了 MyClass 的两个实例 obj1obj2

Dans la classe MyClass, nous définissons un constructeur avec des paramètres et utilisons le paramètre metaclass pour spécifier la métaclasse SingletonType. Étant donné que la classe MyClass utilise la métaclasse SingletonType, elle a un comportement singleton. Dans le programme, nous créons deux instances de MyClass, obj1 et obj2, puis imprimons leurs adresses mémoire pour vérifier s'il s'agit du même objet. . Enfin, nous appelons la méthode sur les deux instances et le résultat devrait être le même.

Décorateur : 🎜rrreee🎜Dans le code ci-dessus, nous définissons une fonction de décorateur nommée singleton. Dans la fonction singleton, nous créons un dictionnaire instances qui stocke des instances uniques de chaque classe. Ensuite, nous définissons une fonction interne appelée get_instance pour obtenir l'instance singleton. Dans la fonction get_instance, nous vérifions le dictionnaire instances et si la classe n'a pas déjà d'instance, créons une nouvelle instance et l'ajoutons aux instances. Enfin, nous renvoyons l'instance dans le dictionnaire. 🎜🎜Appliquez le décorateur @singleton sur la classe MyClass pour la convertir en classe singleton. Puisque ce décorateur opère sur des classes, il peut facilement convertir n’importe quelle classe normale en classe singleton. Dans le programme, nous créons deux instances de MyClass, obj1 et obj2, puis imprimons leurs adresses mémoire pour vérifier s'il s'agit du même objet. . Enfin, nous appelons la méthode sur les deux instances et le résultat devrait être le même. 🎜🎜Module : 🎜rrreeerrreee🎜Dans le code ci-dessus, nous définissons la classe MyClass dans un module indépendant mymodule.py et la créons dedans. Une instance singleton my_singleton . Ensuite, dans un autre fichier main.py, nous importons l'instance my_singleton du module mymodule et l'utilisons pour appeler say_hello () méthode. 🎜🎜Étant donné que les modules Python sont automatiquement exécutés lors de la première importation, nous pouvons profiter de cette fonctionnalité pour créer des instances singleton. Dans le module mymodule.py, nous pouvons garantir que my_singleton n'est créé qu'une seule fois et le partager avec d'autres parties du programme. 🎜🎜nouvelle méthode : 🎜rrreee🎜Dans le code ci-dessus, nous changeons le constructeur de la classe MyClass en méthode __new__() et utilisons _instancecode> variable de classe pour stocker l’instance singleton. Dans la méthode __new__(), nous vérifions la variable _instance et si la classe n'a pas déjà d'instance, créons une nouvelle instance et l'ajoutons à _instance. Enfin, nous renvoyons l'instance dans <code>_instance. 🎜🎜Dans le programme, nous créons deux instances de MyClass, obj1 et obj2, puis imprimons leurs adresses mémoire pour vérifier si elles sont identiques objet. Enfin, nous appelons la méthode sur les deux instances et le résultat devrait être le même. 🎜🎜Quelle que soit la méthode utilisée pour implémenter le modèle singleton, vous devez faire attention aux problèmes tels que la sécurité des threads et l'évolutivité. Par conséquent, lors du développement réel, veuillez examiner attentivement vos besoins et choisir une implémentation appropriée. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer