tags:

views:

1300

answers:

5

With a class in python, how do i define a function to print every single instance of the class in a format defined in the function.

+3  A: 

Same as almost all other OO langauges, keep all instances of the class in a collection of some kind.

You can try this kind of thing.

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

Now you can do this.

object= MyClassFactory( args, ... )
print MyClassFactory.theWholeList
S.Lott
Not quite correct. Some languages offer access to their object memory. In these languages, eg Smalltalk and Ruby, you query ask a class for all its instances. (Actually, I am surprised Python doesnt offer that as well.)
Adrian
@Adrian Kuhn: see @NXC's post on Smalltalk's allInstances capability. Maybe Ruby is the last holdout?
S.Lott
I'd personally rather not see the interpreter suffer extra overhead always providing something which isn't always required, especially when its - as demonstrated - trivially easy to implement when it is.
Matthew Trevor
+2  A: 

Maybe you mean something like __str__:

object.__str__(self)

Called by the str() built-in function and by the print statement to compute the “informal” string representation of an object. This differs from repr() in that it does not have to be a valid Python expression: a more convenient or concise representation may be used instead. The return value must be a string object.

A trivial example:

>>> class dummy(object):
...     def __init__(self):
...      pass
...     def __str__(self):
...      return "I am a dummy"
...     
>>> d1=dummy()
>>> d2=dummy()
>>> print d1,d2
I am a dummy I am a dummy
>>>
gimel
+11  A: 

I see two options in this case:

Garbage collector

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

This has the disadvantage of being very slow when you have a lot of objects, but works with types over which you have no control.

Use a mixin and 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

In this case, all the references get stored as a weak reference in a list. If you create and delete a lot of instances frequently, you should clean up the list of weakrefs after iteration, otherwise there's going to be a lot of cruft.

Another problem in this case is that you have to make sure to call the base class constructor. You could also override __new__, but only the __new__ method of the first base class is used on instantiation. This also works only on types that are under your control.

Edit: The method for printing all instances according to a specific format is left as an exercise, but it's basically just a variation on the for-loops.

Torsten Marek
+1 for the code samples and demo for weak refs. The garbage collector is interesting but probably not that useful for this type of application.
ConcernedOfTunbridgeWells
I know, but it's a last resort if everything else should fail. Maybe I should have put it as option 2.
Torsten Marek
IMO the OP asks about __str__() method.
J.F. Sebastian
+2  A: 

Python doesn't have an equivalent to Smallktalk's #allInstances as the architecture doesn't have this type of central object table (although modern smalltalks don't really work like that eitheer).

As the other poster says, you have to explicitly manage a collection. His suggestion of a factory method that maintains a registry is a perfectly reasonable way to do it. You may wish to do something with weak references so you don't have to explicitly keep track of object disposal.

ConcernedOfTunbridgeWells
+1  A: 

It's not clear if you need to print all class instances at once or when they're initialized, nor if you're talking about a class you have control over vs a class in a 3rd party library.

In any case, I would solve this by writing a class factory using Python metaclass support. If you don't have control over the class, manually update the __metaclass__ for the class or module you're tracking.

See http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html for more information.

Daniel