Bienvenue sur IndexError.

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

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,952 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.

...