Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Comment brider le nombre max d'instances d'une classe ?

+1 vote

Je viens de lire un post sur SO au sujet de la difference entre new et init :
http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init

et j'y ai lu:
Use new when you need to control the creation of a new instance. Use init when you need to control initialization of a new instance.

Brider le nombre max d'instanciations me parait être un exemple intéressant de contrôle
de création...
Mais comment faire exactement ?

Edit: à lire aussi:
http://sametmax.com/la-difference-entre-__new__-et-__init__-en-python/

demandé 9-Aou-2015 par buffalo974 (2,886 points)
edité 9-Aou-2015 par buffalo974

1 Réponse

+6 votes
 
Meilleure réponse

Comme ça (python 3) :

MAX_COUNT = 5    # pour l'exemple

class X:
    counter = 0    # variable de classe
    def __new__(cls):
        if X.counter < MAX_COUNT:
            X.counter += 1
            return super().__new__(cls)
        else:
            raise RuntimeError('maximum instances exeeded')

Une fois 5 instances crées, il devient impossible d'en créer de nouvelles.

répondu 9-Aou-2015 par yoch (2,514 points)
sélectionné 9-Aou-2015 par buffalo974

Note que c'est également courant de s'en servir pour implémenter le pattern singleton, comme ceci :

class Singleton:
    one = None
    def __new__(cls):
        if Singleton.one is None:   # si jamais instancié, on crée l'instance
            Singleton.one = super().__new__(cls)
        return Singleton.one


>>> s1 = Singleton()
>>> s2 = Singleton()
>>> s1 is s2
True

La réponse donnée n’est pas complète. Une fois les 5 instances de la classe X en place, si on supprime une instance, il n’est pas possible d’en créer une nouvelle pour autant alors qu’il n’y a plus que 4 instances en cours. Il faut donc au moins implémenter la méthode __del__:

def __del__(self):
    if X.counter > 0:
        X.counter -= 1

Néanmoins attention, la méthode dépend du ramasse-miettes…

Et il faut aussi savoir que si quelqu'un ou quelque chose modifie la variable MAX_COUNT directement il pourra alors créer de nouvelles instances...

@etno712: Oui, c'est plus complet comme ça. J'ai voulu simplifier l'exemple au maximum.

@Abject: Bien évidement. Pour être plus idiomatique, on devrait peut-être écrire _MAX_COUNT, mais il n'existe pas de moyen d'empêcher quelqu'un de modifier du code s'il le veut.

...