92 votes

Impression de toutes les instances d'une classe

Avec une classe en Python, comment définir une fonction pour imprimer chaque instance de la classe dans un format défini dans la fonction ?

127voto

Torsten Marek Points 27554

Je vois deux options dans ce cas :

Collecteur de déchets

import gc
for obj in gc.get_objects():
    if isinstance(obj, some_class):
        dome_something(obj)

Cette méthode a l'inconvénient d'être très lente lorsque vous avez beaucoup d'objets, mais elle fonctionne avec les types sur lesquels vous n'avez aucun contrôle.

Utiliser un mixin et des weakrefs

from collections import defaultdict
import weakref

class KeepRefs(object):
    __refs__ = defaultdict(list)
    def __init__(self):
        self.__refs__[self.__class__].append(weakref.ref(self))

    @classmethod
    def get_instances(cls):
        for inst_ref in cls.__refs__[cls]:
            inst = inst_ref()
            if inst is not None:
                yield inst

class X(KeepRefs):
    def __init__(self, name):
        super(X, self).__init__()
        self.name = name

x = X("x")
y = X("y")
for r in X.get_instances():
    print r.name
del y
for r in X.get_instances():
    print r.name

Dans ce cas, toutes les références sont stockées sous la forme d'une référence faible dans une liste. Si vous créez et supprimez fréquemment un grand nombre d'instances, vous devriez nettoyer la liste des références faibles après l'itération, sinon il y aura beaucoup de déchets.

Un autre problème dans ce cas est qu'il faut s'assurer d'appeler le constructeur de la classe de base. Vous pourriez également surcharger __new__ mais seulement le __new__ de la première classe de base est utilisée lors de l'instanciation. Cela ne fonctionne également que pour les types que vous contrôlez.

Editar : La méthode d'impression de toutes les instances selon un format spécifique est laissée à l'état d'exercice, mais il s'agit essentiellement d'une variante de la méthode for -loops.

35voto

Vous ne devez importer RIEN ! Utilisez simplement "self". Voici comment procéder

class A:
    instances = []
    def __init__(self):
        self.__class__.instances.append(self)
print('\n'.join(A.instances)) #this line was suggested by @anvelascos

C'est aussi simple que cela. Pas de modules ou de bibliothèques importés

33voto

MirkoT Points 31

Vous devez créer une liste statique dans votre classe et ajouter un fichier weakref à chaque instance afin que le ramasse-miettes puisse nettoyer vos instances lorsqu'elles ne sont plus nécessaires.

import weakref

class A:
    instances = []
    def __init__(self, name=None):
        self.__class__.instances.append(weakref.proxy(self))
        self.name = name

a1 = A('a1')
a2 = A('a2')
a3 = A('a3')
a4 = A('a4')

for instance in A.instances:
    print(instance.name)

9voto

Fabio Caccamo Points 6

Un code très intéressant et utile, mais qui présente un gros problème : la liste est toujours plus grande et il n'est jamais nettoyé, pour le tester il suffit d'ajouter print(len(cls.__refs__[cls])) à la fin de la get_instances méthode.

Voici un correctif pour le get_instances méthode :

__refs__ = defaultdict(list)

@classmethod
def get_instances(cls):
    refs = []
    for ref in cls.__refs__[cls]:
        instance = ref()
        if instance is not None:
            refs.append(ref)
            yield instance
    # print(len(refs))
    cls.__refs__[cls] = refs

ou encore en utilisant WeakSet :

from weakref import WeakSet

__refs__ = defaultdict(WeakSet)

@classmethod
def get_instances(cls):
    return cls.__refs__[cls]

7voto

S.Lott Points 207588

Comme dans presque tous les autres langages OO, toutes les instances de la classe sont conservées dans une collection.

Vous pouvez essayer ce genre de choses.

class MyClassFactory( object ):
    theWholeList= []
    def __call__( self, *args, **kw ):
         x= MyClass( *args, **kw )
         self.theWholeList.append( x )
         return x

Vous pouvez maintenant le faire.

object= MyClassFactory( args, ... )
print MyClassFactory.theWholeList

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X