Maison >développement back-end >Tutoriel Python >Introduction à l'utilisation du mode singleton sous la métaclasse Python (exemple de code)

Introduction à l'utilisation du mode singleton sous la métaclasse Python (exemple de code)

不言
不言original
2018-09-12 15:13:211733parcourir

Cet article vous apporte une introduction à l'utilisation du mode singleton sous les métaclasses Python (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1. Qu'est-ce que la métaclasse Python

Article de référence Qu'est-ce que la métaclasse Python ? Introduction aux métaclasses Python

2. Qu'est-ce que le modèle singleton

Le modèle singleton (modèle Singleton) est un modèle de conception de logiciels couramment utilisé. Il ne contient qu’une seule classe spéciale appelée singleton dans sa structure de base. Le mode singleton peut garantir qu'il n'y a qu'une seule instance d'une classe dans le système et que l'instance est facilement accessible depuis le monde extérieur, facilitant ainsi le contrôle du nombre d'instances et économisant les ressources du système. Si vous souhaitez qu'un seul objet d'une certaine classe existe dans le système, le modèle singleton est la meilleure solution.

Comment s'assurer qu'une classe ne possède qu'une seule instance et que cette instance soit facile d'accès ? Définir une variable globale garantit que l'objet est accessible à tout moment, mais cela ne nous empêche pas d'instancier plusieurs objets. Une meilleure solution consiste à confier à la classe elle-même la responsabilité de sauvegarder sa seule instance. Cette classe garantit qu'aucune autre instance n'est créée et fournit une méthode pour accéder à l'instance. C'est la motivation du modèle derrière le modèle singleton.

3. Utilisez __new__ pour implémenter le mode singleton

# -*- coding: utf8 -*-

class Singleton(object):
    def __init__(self):
        print 'entrance of __init__'

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

if __name__ == '__main__':
    s1 = Singleton()
    s2 = Singleton()

    print s1, s2

En Python, la fonction __new__ est généralement utilisée pour implémenter le mode singleton . La fonction __new__ est responsable de la construction des objets, similaire au constructeur en C++. Par conséquent, afin que la classe ne crée qu'une seule instance d'objet, nous pouvons surcharger le comportement de la fonction __new__ afin qu'elle ne puisse construire qu'une seule instance. Dans le code ci-dessus, un attribut _instance est affecté à la classe Singleton. Si l'attribut _instance est Aucun, un objet instance est créé et l'attribut _instance fait référence à (pointe vers) l'objet. Sinon, l'objet référencé par _instance est renvoyé directement. . Ainsi, s1 et s2 dans le code font en fait référence au même objet mémoire.

4. Utilisez la métaclasse __call__ pour implémenter singleton

# -*- coding: utf8 -*-

# 单例模式
class SingletonMetaClass(type):
    def __init__(cls, *args, **kwargs):
        """
        初始化类
        :param args:
        :param kwargs:
        """
        print 'MetaClass.__init__ called'
        print cls._instance
        super(SingletonMetaClass, cls).__init__(*args, **kwargs)


    def __new__(cls, name, bases, attrs):
        """
        创建类,负责类的行为和属性的创建
        :param name:
        :param bases:
        :param attrs:
        :return:
        """
        print 'MetaClass.__new__ called'

        # 单例模式
        cls._instance = None

        return type.__new__(cls, name, bases, attrs)

    # __call__方法其实和类的创建过程和实例化没有多大关系了,定义了__call__方法才能被使用函数的方式执行。
    # 被该元类创建的类,属于该元类的一个实例。因此创建其实例的时候,会调用元类的__call_方法
    def __call__(cls, *args, **kwargs):
        """
        使类变为可调用对象
        :param args:
        :param kwargs:
        :return:
        """
        print 'MetaClass.__call__ called'
        if cls._instance is None:
            # 这里会去调用类的__new__函数
            cls._instance = super.__call__(SingletonMetaClass, cls).__call__(*args, **kwargs)
        return cls._instance

class A():
    __metaclass__ = SingletonMetaClass

    def __new__(cls, *args, **kwargs):
        print 'A.__new__ called'
        return super(A, cls).__new__(cls, *args, **kwargs)

if __name__ == '__main__':
    # 因为类A是SingletonMetaClass的一个实例,执行A()时会调用元类SingletonMetaClass的__call__方法
    a1 = A()
    print a1
    a2 = A()
    print a2

Nous savons qu'en Python, les classes sont aussi des objets, et les métaclasses sont des classes qui créent des classes, donc les classes sont en fait ci-dessus est l'objet instance de la métaclasse . En Python, si un objet définit la méthode __call__, alors l'objet est un objet appelable, ce qui signifie que l'objet peut être appelé en appelant une fonction.

La méthode __new__ de Python est responsable de la création des objets, et la méthode __init__ est responsable de l'initialisation des objets. Dans le code ci-dessus, un objet de classe A ne peut être créé qu'après la création de la classe A Par conséquent, afin de créer d'abord la classe A, les méthodes __new__ et __init__ de SingletonMetaClass seront exécutées en premier. Lorsque l'instruction A() est exécutée pour créer un objet de classe A, selon la définition de la méthode __call__, puisque la classe A est un objet de la métaclasse SingletonMetaClass, on peut s'attendre à ce que la méthode __call__ de la métaclasse SingletonMetaClass soit appelée .

Ainsi, les méthodes __new__ et __init__ de SiingletonMetaClass dans le code ci-dessus ne sont exécutées qu'une seule fois, et SingletonMetaClass sera appelée à chaque fois que A() est appelé pour créer une instance de classe A. Méthode __call__. Par conséquent, afin d'implémenter le mode singleton, nous déterminons si l'attribut _instance de cls est None dans la méthode __call__ de la métaclasse. S'il est None, nous appelons la méthode __call__ de la classe parent de la métaclasse (c'est-à-dire type), type. __call_ La _method appellera la méthode __new__ de la classe A pour créer une instance de la classe A, puis pointera l'attribut _instance vers l'instance, obtenant ainsi une seule instance. Ce qui suit est le résultat d'une exécution :

MetaClass.__new__ called
MetaClass.__init__ called
None
MetaClass.__call__ called
A.__new__ called
<__main__.A object at 0x00000000036D2EB8>
MetaClass.__call__ called
<__main__.A object at 0x00000000036D2EB8>

Recommandations associées :

Exemples de Python utilisant le modèle de chaîne de responsabilité et le modèle d'itérateur dans les modèles de conception

Introduction à l'implémentation singleton de Python à l'aide du pool Redis

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn