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 ?
Réponses
Trop de publicités?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.
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
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)
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]
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
- Réponses précédentes
- Plus de réponses