Keeping track of subclasses and instances?

George Sakkis george.sakkis at gmail.com
Wed Oct 10 22:41:07 EDT 2007


On Oct 10, 9:19 pm, Karlo Lozovina <_kar... at mosor.net> wrote:
> Larry Bates wrote:
> > I'm not completely sure I understand the question but here goes.
> > Instances of
> > classes are classes can be stored in lists or dictionaries.  In lists you
> > reference them via their index (or iterate over them) and in dictionaries
> > you can give them a name that is used as a key.
>
> I wish if it were that simple :).
>
> Here is a longer description - I have a function that given input creates a
> custom class and returns it back. The user is free to subclass that (even
> more, he should do that), and of course he will make instances of those
> subclasses. Now, my question is how to keep track of subclasses and their
> instances, without the need for user interaction (appending them to a list,
> or adding to dictionary)?
>
> Thanks,
>
> --
> Karlo Lozovina - Mosor


I guess Larry's actual question was why do *you* need to keep track of
users' instances and subclasses and don't let them keep track on their
own if/when they need it. I realize there are legitimate use cases for
this but it's not typical. Anyway, here's something to get you
started; all a user has to do is derive (directly or indirectly) from
InstanceTracker and, if a class C defines __init__,
super(C,self).__init__() should be called explicitly:


from collections import deque
from weakref import WeakKeyDictionary

class InstanceTracker(object):
    def __init__(self):
        try: all = self.__class__.__dict__['__instances__']
        except KeyError:
            self.__class__.__instances__ = all = WeakKeyDictionary()
        all[self] = None

def iter_instances(cls):
    return iter(cls.__dict__.get('__instances__',[]))

def iter_descendant_classes(cls):
    memo = set()
    unvisited = deque(cls.__subclasses__())
    while unvisited:
        top = unvisited.popleft()
        if top not in memo:
            memo.add(top); yield top
        unvisited.extend(top.__subclasses__())

#----- example --------------------------------------
if __name__ == '__main__':

    class A(InstanceTracker): pass
    class B1(A): pass
    class B2(A): pass
    class C1(B1,B2):
        def __init__(self):
            super(C1,self).__init__()
    class C2(B1,B2): pass
    class D(C1,C2): pass

    items = [A(),B1(),B2(),C1(),C1(),D(),A(),B2()]
    print ' * Instances per class'
    for c in iter_descendant_classes(A):
        print c, list(iter_instances(c))

    print ' * Instances per class (after delete)'
    del items
    for c in iter_descendant_classes(A):
        print c, list(iter_instances(c))


HTH,
George




More information about the Python-list mailing list