web-dev-qa-db-fra.com

Python classes avec une seule instance: quand créer une instance de classe (unique) et quand travailler avec la classe à la place?

Étant donné une classe Python qui ne sera instanciée qu'une seule fois, c'est-à-dire qu'il n'y aura qu'un seul objet de la classe. Je me demandais dans quels cas il était logique de créer une seule instance de classe au lieu de travailler directement avec la classe à la place.

Il existe un question similaire, mais il a un objectif différent:

  1. il s'agit de regrouper les variables et fonctions globales dans une classe et
  2. Ce n'est pas spécifique à Python. Ce dernier signifie qu'il ne tient pas compte du fait que (en Python) les classes sont également des objets.

MISE À JOUR:

En Python, je peux faire ce qui suit avec les classes et les objets:

class A(object):
    pass

A.some_state_var = True
# Then later
A.some_state_var = False


my_a = A()

my_a.some_state_var = True
# Then later
my_a.some_state_var = False

Je ne vois donc pas comment le choix entre une classe et une instance de cette classe concerne l'état (en Python). Je peux maintenir un état avec l'un ou l'autre.

De plus, la motivation pour créer ma classe/instance de classe ne consiste pas à appliquer une exigence Singleton.

De plus, il ne s'agit pas tant de créer un nouveau type.

La motivation est de regrouper le code et les données connexes et d'avoir une interface avec eux. C'est pourquoi je l'ai initialement modélisé en tant que classe dans un diagramme de classes. Ce n'est que pour l'implémentation que j'ai commencé à me demander s'il fallait instancier cette classe ou non.

11
langlauf.io

Étant donné une classe Python qui ne sera instanciée qu'une seule fois, c'est-à-dire qu'il n'y aura qu'un seul objet de la classe. Je me demandais dans quels cas il était logique de créer une seule instance de classe au lieu de travailler directement avec la classe à la place.

C'est donc ça:

class Singleton:
    '''don't bother instantiating me'''
    clsvar1 = 'foo'

    @classmethod
    def foobar(cls, *args, **kwargs):
        if condition():
            cls.clsvar1 = 'bar'

contre ça?

class Singleton:
    '''instantiate and use me'''
    def __init__(self):
        self.var1 = 'foo'

    def foobar(self, *args, **kwargs):
        if condition():
            self.var1 = 'bar'

Recommandation

Je préférerais certainement celui qui est destiné à être instancié. Lorsque vous créez un "type de chose", cela implique que vous créez des choses de ce type.

La motivation est de regrouper le code et les données connexes et d'avoir une interface avec eux.

Cela dit, pourquoi ne pas simplement utiliser un module car tout ce que vous voulez, c'est un espace de noms? Les modules sont des singletons, du code et des données liés au groupe, ce qui est un peu plus simple et serait probablement considéré comme plus Pythonic:

var1 ='foo'

def foobar(*args, **kwargs):
    global var1
    if condition():
        var1 = 'bar'

Donc, l'utilisation serait au lieu de:

from modules.singleton import Singleton
Singleton.foobar()

ou

from modules.singleton import Singleton
the_singleton = Singleton()
the_singleton.foobar()

faites ceci:

from modules import singleton
singleton.foobar()
16
Aaron Hall

Je me demandais dans quels cas il était logique de créer une instance de classe unique au lieu de travailler directement avec la classe à la place.

C'est l'une de ces choses qui provoquera une guerre de religion si vous y entrez trop.

Mais en général, une pratique que j'ai vue à plusieurs reprises est que les méthodes de classe ne devraient se préoccuper que de créer des instances de cette classe.

Si vous pensez à ce qu'est une classe, quel est son but/comportement, alors cela a du sens. Le but d'une classe est de créer des instances d'objets basés sur lui-même. C'est un plan qui peut également construire le bâtiment. Une classe "Utilisateur" crée des objets "utilisateur". Une classe "Chien" crée des objets "chien" etc etc

Étant donné que c'est le comportement d'une classe, il est logique que les méthodes que vous ajoutez à la classe "X" se préoccupent de créer des objets "x".

Donc, même si vous n'avez besoin que d'un seul objet "x", vous devez toujours l'instancier.

L'ajout de méthodes à la classe X qui ne sont pas liées à la création d'instances d'objets "x" peut entraîner une confusion du code inattendu. Il y a bien sûr des tonnes d'exemples dans le monde réel où les gens l'ont fait de toute façon, mais comme je l'ai dit, ce chemin mène à la guerre de religion.

2
Cormac Mulhall