import weakref, inspect class MetaInstanceTracker(type): def __new__(cls, name, bases, ns): t = super(MetaInstanceTracker, cls).__new__(cls, name, bases, ns) t.__instance_refs__ = [] return t def __instances__(self): instances = [(r, r()) for r in self.__instance_refs__] instances = filter(lambda (x,y): y is not None, instances) self.__instance_refs__ = [r for (r, o) in instances] return [o for (r, o) in instances] def __call__(self, *args, **kw): instance = super(MetaInstanceTracker, self).__call__(*args, **kw) self.__instance_refs__.append(weakref.ref(instance)) return instance class InstanceTracker: __metaclass__ = MetaInstanceTracker class MetaAutoReloader(MetaInstanceTracker): def __new__(cls, name, bases, ns): new_class = super(MetaAutoReloader, cls).__new__( cls, name, bases, ns) f = inspect.currentframe().f_back for d in [f.f_locals, f.f_globals]: if d.has_key(name): old_class = d[name] for instance in old_class.__instances__(): instance.change_class(new_class) new_class.__instance_refs__.append( weakref.ref(instance)) # this section only works in 2.3 for subcls in old_class.__subclasses__(): newbases = () for base in subcls.__bases__: if base is old_class: newbases += (new_class,) else: newbases += (base,) subcls.__bases__ = newbases break return new_class class AutoReloader: __metaclass__ = MetaAutoReloader def change_class(self, new_class): self.__class__ = new_class class Bar(AutoReloader): pass class Baz(Bar): pass b = Bar() b2 = Baz() class Bar(AutoReloader): def meth(self, arg): print arg if __name__ == '__main__': # now b is "upgraded" to the new Bar class: b.meth(1) # new in 2.3, Baz instances join the fun: b2.meth(2) # new Baz() instances now play too: Baz().meth(3)