a class auto upgrader
Michael Hudson
mwh at python.net
Thu Oct 31 09:42:45 EST 2002
Michael Hudson <mwh at python.net> writes:
> I'm on my way out, so I don't really have time to explain this, but
> here's a little something that may ease interactive development with
> Python.
Here's a better version of what I had before.
It doesn't interact well with inheritance (see comments at the end),
and there's not a lot I can do about that, because the __bases__
attribute of new style classes is not mutable. This might change in
Python 2.3...
hey-i-don't-care-if-noone's-listening,-i-think-it's-neat-ly y'rs
M.
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))
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)
# unfortunately, Baz instances can't join the fun:
try:
b2.meth()
except AttributeError:
print "nuts"
# even worse (and, actually, harder to deal with):
# new Baz() instances can't play either:
# unfortunately, Baz instances can't join the fun:
try:
Baz().meth()
except AttributeError:
print "nuts again"
--
I've even been known to get Marmite *near* my mouth -- but never
actually in it yet. Vegamite is right out.
UnicodeError: ASCII unpalatable error: vegamite found, ham expected
-- Tim Peters, comp.lang.python
More information about the Python-list
mailing list