Imprimiendo todas las instancias de una clase

Con una clase en Python, ¿cómo defino una función para imprimir cada instancia de la clase en un formato definido en la función?

Veo dos opciones en este caso:

Recolector de basura

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

Esto tiene la desventaja de ser muy lento cuando tiene muchos objetos, pero funciona con tipos sobre los que no tiene control.

Usa un mixin y puntos débiles.

 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 

En este caso, todas las referencias se almacenan como una referencia débil en una lista. Si creas y borras muchas instancias con frecuencia, deberías limpiar la lista de referencias débiles después de la iteración, de lo contrario habrá mucha navegación.

Otro problema en este caso es que debe asegurarse de llamar al constructor de la clase base. También puede anular __new__ , pero solo se __new__ método __new__ de la primera clase base en la __new__ de instancias. Esto también funciona solo en los tipos que están bajo su control.

Edición : el método para imprimir todas las instancias según un formato específico se deja como ejercicio, pero básicamente es solo una variación de los bucles for .

weakref crear una lista estática en su clase y agregar una weakref a cada instancia para que el recolector de basura pueda limpiar sus instancias cuando ya no sean necesarias.

 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) 

Código muy agradable y útil, pero tiene un gran problema: la lista siempre es más grande y nunca se limpia, para probarla simplemente agregue print(len(cls.__refs__[cls])) al final del método get_instances .

Aquí una solución para el método get_instances :

 __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 

o alternativamente se podría hacer usando WeakSet:

 from weakref import WeakSet __refs__ = defaultdict(WeakSet) @classmethod def get_instances(cls): return cls.__refs__[cls] 

Igual que en casi todos los demás idiomas OO, mantenga todas las instancias de la clase en una colección de algún tipo.

Puedes probar este tipo de cosas.

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

Ahora puedes hacer esto.

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

Python no tiene un equivalente a #allInstances de Smallktalk, ya que la architecture no tiene este tipo de tabla de objetos central (aunque los smalltalks modernos tampoco funcionan así).

Como dice el otro póster, debes administrar explícitamente una colección. Su sugerencia de un método de fábrica que mantiene un registro es una forma perfectamente razonable de hacerlo. Es posible que desee hacer algo con referencias débiles para no tener que hacer un seguimiento explícito de la eliminación de objetos.

No está claro si necesita imprimir todas las instancias de la clase a la vez o cuando están inicializadas, ni si está hablando de una clase que tiene control sobre una clase en una biblioteca de terceros.

En cualquier caso, resolvería esto escribiendo una fábrica de clases utilizando el soporte de metaclase de Python. Si no tiene control sobre la clase, actualice manualmente __metaclass__ para la clase o el módulo que está siguiendo.

Consulte http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html para obtener más información.