Table des matières
La meilleure façon d'implémenter un singleton en Python
Méthode de mise en œuvre
Méthode 1 : Décorateur
Méthode 2 : Classe de base
Méthode 3 : Métaclasse
Méthode 4 : Renvoyez le décorateur de la classe du même nom
Méthode 5 : Module
Méthode recommandée
Le rôle de la métaclasse
Bien sûr
Versions compatibles Python 2 et 3
Correction
Maison développement back-end Tutoriel Python Quelle est la meilleure façon d'implémenter un singleton en Python ?

Quelle est la meilleure façon d'implémenter un singleton en Python ?

Dec 17, 2024 pm 04:07 PM

What is the best way to implement a singleton in Python?

La meilleure façon d'implémenter un singleton en Python

Bien que les avantages et les inconvénients du modèle de conception singleton ne soient pas au centre de cet article, cet article explorera comment pour implémenter le singleton en Python de la meilleure façon possible. Implémentez ce modèle de manière pythonique. Ici, « le plus pythonique » signifie suivre le « principe de la moindre surprise ».

Méthode de mise en œuvre

Méthode 1 : Décorateur

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
Copier après la connexion
Copier après la connexion
Copier après la connexion

Avantages :

  • Le décorateur a du sexe supplémentaire, plus intuitif que l’héritage multiple.

Inconvénients :

  • L'objet créé à l'aide de MyClass() est un véritable objet singleton, mais MyClass lui-même est une fonction, pas une classe, les méthodes de classe ne peuvent donc pas être appelées.

Méthode 2 : Classe de base

class Singleton(object):
    _instance = None

    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass
Copier après la connexion
Copier après la connexion

Avantages :

  • C'est une vraie classe.

Inconvénients :

  • Héritage multiple, désagréable. Lors de l'héritage d'une deuxième classe de base, __new__ peut être remplacé.

Méthode 3 : Métaclasse

class Singleton(type):
    _instances = {}

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

# Python2
class MyClass(BaseClass):
    __metaclass__ = Singleton

# Python3
class MyClass(BaseClass, metaclass=Singleton):
    pass
Copier après la connexion

Avantages :

  • C'est une vraie classe.
  • Les successions sont automatiquement couvertes.
  • Utilisez __metaclass__ correctement (et faites-moi le comprendre).

Inconvénients :

  • Aucun inconvénient.

Méthode 4 : Renvoyez le décorateur de la classe du même nom

def singleton(class_):
    class class_w(class_):
        _instance = None

        def __new__(class_, *args, **kwargs):
            if class_w._instance is None:
                class_w._instance = super(class_w, class_).__new__(class_, *args, **kwargs)
                class_w._instance._sealed = False
            return class_w._instance

        def __init__(self, *args, **kwargs):
            if self._sealed:
                return
            super(class_w, self).__init__(*args, **kwargs)
            self._sealed = True

    class_w.__name__ = class_.__name__
    return class_w

@singleton
class MyClass(BaseClass):
    pass
Copier après la connexion

Avantages :

  • C'est une vraie classe.
  • Les successions sont automatiquement couvertes.

Inconvénients :

  • Y a-t-il une surcharge liée à la création de deux classes pour chaque classe pour laquelle vous souhaitez devenir un singleton ? Bien que cela fonctionne bien dans mon cas, je crains que cela ne soit pas évolutif. Quel est le but de l'attribut
  • _sealed ?
  • Vous ne pouvez pas utiliser super() pour appeler des méthodes portant le même nom dans une classe de base car elles seraient récursives. Cela signifie que __new__ ne peut pas être personnalisé, et qu'une classe qui nécessite l'appel de __init__ ne peut pas non plus être sous-classée.

Méthode 5 : Module

Module Singleton singleton.py.

Avantages :

  • Mieux vaut simple que compliqué.

Inconvénients :

  • Pas d'instanciation différée.

Méthode recommandée

Je recommande d'utiliser la Méthode 2, mais il est préférable d'utiliser des métaclasses au lieu de classes de base. Voici un exemple d'implémentation :

class Singleton(type):
    _instances = {}

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

class Logger(object):
    __metaclass__ = Singleton
Copier après la connexion

Ou en Python3 :

class Logger(metaclass=Singleton):
    pass
Copier après la connexion

Si vous souhaitez que __init__ s'exécute à chaque fois qu'une classe est appelée, ajoutez le code suivant à Singleton.__call__ In l'instruction if :

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le rôle de la métaclasse

Une métaclasse est une classe de classes, c'est-à-dire qu'une classe est une instance de sa métaclasse. La métaclasse d'un objet en Python peut être trouvée via type(obj). Les nouvelles classes normales sont de type type. Le Logger ci-dessus sera de type class 'your_module.Singleton', tout comme la (seule) instance de Logger sera de type class 'your_module.Logger' . Lorsqu'un enregistreur est appelé à l'aide de Logger(), Python demande d'abord à la métaclasse Singleton du Logger ce qu'il doit faire, permettant la création d'instances préemptives. Le processus est similaire à la façon dont Python demande à une classe ce qu'elle doit faire avec ses attributs en appelant __getattr__, et vous référencez ses attributs en faisant myclass.attribute.

Les métaclasses déterminent essentiellement ce que signifie la classe appelante et comment implémenter cette signification. Voir par exemple http://code.activestate.com/recipes/498149/ qui utilise des métaclasses pour recréer essentiellement des structures de style C en Python. Sujet de discussion [Quels sont les cas d'utilisation spécifiques des métaclasses ? ](https://codereview.stackexchange.com/questions/82786/what-are-some-concrete-use-cases-for-metaclasses) fournit également quelques exemples, qui sont généralement liés à la programmation déclarative, en particulier dans l'ORM utilisé dans .

Dans ce cas, si vous utilisez votre Méthode 2 et qu'une sous-classe définit une méthode __new__, elle sera exécutée à chaque fois que SubClassOfSingleton() est appelée, car elle est responsable de l'appel des méthodes qui renvoyer les instances stockées. Avec les métaclasses, elle n'est exécutée qu'une seule fois, lors de la création de l'instance unique. Vous devez personnaliser la définition de la classe appelante, qui est déterminée par son type.

En général, il est logique d'utiliser des métaclasses pour implémenter des singletons. Un singleton est spécial car son instance n'est créée qu'une seule fois, tandis qu'une métaclasse est une implémentation personnalisée d'une classe créée qui la fait se comporter différemment d'une classe normale. L'utilisation d'une métaclasse vous donne plus de contrôle alors que vous auriez autrement besoin de personnaliser la définition de votre classe singleton.

Bien sûr

Votre singleton n'a pas besoin d'héritage multiple (car la métaclasse n'est pas une classe de base), mais pour que l'héritage crée une sous-classe d'une classe, vous devez vous assurer que le singleton la classe est la première/La métaclasse la plus à gauche redéfinit __call__. Il est peu probable que cela pose un problème. Le dictionnaire d'instance ne se trouve pas dans l'espace de noms de l'instance, il ne peut donc pas être écrasé accidentellement.

Vous entendrez également que le modèle singleton viole le « principe de responsabilité unique », ce qui signifie que chaque classe ne doit faire qu'une seule chose. De cette façon, vous n'avez pas à vous soucier de casser une chose que fait le code lorsque vous devez en modifier un autre, car ils sont indépendants et encapsulés. L'implémentation de la métaclasse réussit ce test. Les métaclasses sont chargées d'appliquer le modèle, en créant des classes et des sous-classes qui n'ont pas besoin de savoir qu'elles sont des singletons. La méthode 1 échoue à ce test, comme vous l'avez souligné avec "MyClass elle-même est une fonction, pas une classe, donc les méthodes de classe ne peuvent pas être appelées".

Versions compatibles Python 2 et 3

Écrire du code en Python 2 et 3 nécessite un schéma légèrement plus compliqué. Étant donné que les métaclasses sont généralement des sous-classes de la classe de type, vous pouvez utiliser une métaclasse pour créer dynamiquement une classe de base intermédiaire avec elle comme métaclasse au moment de l'exécution, puis utiliser cette classe de base comme classe de base pour une classe de base singleton publique. C'est plus facile à dire qu'à faire, comme suit :

def singleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@singleton
class MyClass(BaseClass):
    pass
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'ironie de cette approche est qu'elle utilise des sous-classes pour implémenter des métaclasses. Un avantage possible est que, contrairement à une métaclasse pure, isinstance(inst, Singleton) renverra True.

Correction

Concernant un autre sujet, vous l'avez peut-être remarqué, mais l'implémentation de la classe de base dans votre message d'origine était erronée. Pour référencer des _instances dans une classe, vous devez utiliser super() ou une méthode statique de la méthode de classe, car la classe réelle n'a pas encore été créée au moment de l'appel. Tout cela est également vrai pour les implémentations de métaclasses.

class Singleton(object):
    _instance = None

    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, BaseClass):
    pass
Copier après la connexion
Copier après la connexion

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 de ce site Web
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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Bubble Gum Simulator Infinity - Comment obtenir et utiliser les clés royales
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
<🎜>: Grow A Garden - Guide de mutation complet
3 Il y a quelques semaines By DDD
Nordhold: Système de fusion, expliqué
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Comment déverrouiller le grappin
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1675
14
Tutoriel PHP
1278
29
Tutoriel C#
1257
24
Python vs C: courbes d'apprentissage et facilité d'utilisation Python vs C: courbes d'apprentissage et facilité d'utilisation Apr 19, 2025 am 12:20 AM

Python est plus facile à apprendre et à utiliser, tandis que C est plus puissant mais complexe. 1. La syntaxe Python est concise et adaptée aux débutants. Le typage dynamique et la gestion automatique de la mémoire le rendent facile à utiliser, mais peuvent entraîner des erreurs d'exécution. 2.C fournit des fonctionnalités de contrôle de bas niveau et avancées, adaptées aux applications haute performance, mais a un seuil d'apprentissage élevé et nécessite une gestion manuelle de la mémoire et de la sécurité.

Apprendre Python: 2 heures d'étude quotidienne est-elle suffisante? Apprendre Python: 2 heures d'étude quotidienne est-elle suffisante? Apr 18, 2025 am 12:22 AM

Est-ce suffisant pour apprendre Python pendant deux heures par jour? Cela dépend de vos objectifs et de vos méthodes d'apprentissage. 1) Élaborer un plan d'apprentissage clair, 2) Sélectionnez les ressources et méthodes d'apprentissage appropriées, 3) la pratique et l'examen et la consolidation de la pratique pratique et de l'examen et de la consolidation, et vous pouvez progressivement maîtriser les connaissances de base et les fonctions avancées de Python au cours de cette période.

Python vs. C: Explorer les performances et l'efficacité Python vs. C: Explorer les performances et l'efficacité Apr 18, 2025 am 12:20 AM

Python est meilleur que C dans l'efficacité du développement, mais C est plus élevé dans les performances d'exécution. 1. La syntaxe concise de Python et les bibliothèques riches améliorent l'efficacité du développement. Les caractéristiques de type compilation et le contrôle du matériel de CC améliorent les performances d'exécution. Lorsque vous faites un choix, vous devez peser la vitesse de développement et l'efficacité de l'exécution en fonction des besoins du projet.

Python vs C: Comprendre les principales différences Python vs C: Comprendre les principales différences Apr 21, 2025 am 12:18 AM

Python et C ont chacun leurs propres avantages, et le choix doit être basé sur les exigences du projet. 1) Python convient au développement rapide et au traitement des données en raison de sa syntaxe concise et de son typage dynamique. 2) C convient à des performances élevées et à une programmation système en raison de son typage statique et de sa gestion de la mémoire manuelle.

Quelle partie fait partie de la bibliothèque standard Python: listes ou tableaux? Quelle partie fait partie de la bibliothèque standard Python: listes ou tableaux? Apr 27, 2025 am 12:03 AM

PythonlistSaReparmentofthestandardLibrary, tandis que les coloccules de colocède, tandis que les colocculations pour la base de la Parlementaire, des coloments de forage polyvalent, tandis que la fonctionnalité de la fonctionnalité nettement adressée.

Python: automatisation, script et gestion des tâches Python: automatisation, script et gestion des tâches Apr 16, 2025 am 12:14 AM

Python excelle dans l'automatisation, les scripts et la gestion des tâches. 1) Automatisation: La sauvegarde du fichier est réalisée via des bibliothèques standard telles que le système d'exploitation et la fermeture. 2) Écriture de script: utilisez la bibliothèque PSUTIL pour surveiller les ressources système. 3) Gestion des tâches: utilisez la bibliothèque de planification pour planifier les tâches. La facilité d'utilisation de Python et la prise en charge de la bibliothèque riche en font l'outil préféré dans ces domaines.

Python pour l'informatique scientifique: un look détaillé Python pour l'informatique scientifique: un look détaillé Apr 19, 2025 am 12:15 AM

Les applications de Python en informatique scientifique comprennent l'analyse des données, l'apprentissage automatique, la simulation numérique et la visualisation. 1.Numpy fournit des tableaux multidimensionnels et des fonctions mathématiques efficaces. 2. Scipy étend la fonctionnalité Numpy et fournit des outils d'optimisation et d'algèbre linéaire. 3. Pandas est utilisé pour le traitement et l'analyse des données. 4.Matplotlib est utilisé pour générer divers graphiques et résultats visuels.

Python pour le développement Web: applications clés Python pour le développement Web: applications clés Apr 18, 2025 am 12:20 AM

Les applications clés de Python dans le développement Web incluent l'utilisation des cadres Django et Flask, le développement de l'API, l'analyse et la visualisation des données, l'apprentissage automatique et l'IA et l'optimisation des performances. 1. Framework Django et Flask: Django convient au développement rapide d'applications complexes, et Flask convient aux projets petits ou hautement personnalisés. 2. Développement de l'API: Utilisez Flask ou DjangorestFramework pour construire RestulAPI. 3. Analyse et visualisation des données: utilisez Python pour traiter les données et les afficher via l'interface Web. 4. Apprentissage automatique et AI: Python est utilisé pour créer des applications Web intelligentes. 5. Optimisation des performances: optimisée par la programmation, la mise en cache et le code asynchrones

See all articles