On 5 Mar, 07:31, "Raymond Hettinger" <[EMAIL PROTECTED]> wrote: > I had an idea but no time to think it through. > Perhaps the under-under name mangling trick > can be replaced (in Py3.0) with a suitably designed decorator. > Your challenge is to write the decorator. > Any trick in the book (metaclasses, descriptors, etc) is fair game.
I had some time this lunchtimes and I needed to calm my nerves so I took up your challenge :) Here is my poor effort. I'm sure lots of things are wrong with it but I'm not sure I'll look at it again. from types import MethodType, FunctionType # The suggested localmethod decorator class localmethod(object): def __init__(self, f): self.f = f self.defclass = None self.nextmethod = None def __get__(self, obj, objtype=None): callobj = obj or objtype if callobj.callerclass == self.defclass: return MethodType(self.f, obj, objtype) elif self.nextmethod: return self.nextmethod.__get__(obj, objtype) else: raise AttributeError class BoundMethod(object): def __init__(self, meth, callobj, callerclass): self.meth = meth self.callobj = callobj self.callerclass = callerclass def __call__(self, *args, **kwargs): callobj = self.callobj try: callobj.callerclass = self.callerclass return self.meth(*args, **kwargs) finally: callobj.callerclass = None # A 'mormal' method decorator is needed as well class method(object): def __init__(self, f): self.f = f self.defclass = None def __get__(self, obj, objtype=None): callobj = obj or objtype return BoundMethod(MethodType(self.f, obj, objtype), callobj, self.defclass) class Type(type): def __new__(self, name, bases, attrs): for attr, val in attrs.items(): if type(val) == FunctionType: attrs[attr] = method(val) return type.__new__(self, name, bases, attrs) def __init__(self, name, bases, attrs): for attr, val in attrs.iteritems(): if type(val) == localmethod: val.defclass = self for base in self.mro()[1:]: if attr in base.__dict__: nextmethod = base.__dict__[attr] val.nextmethod = nextmethod break elif type(val) == method: val.defclass = self class Object(object): __metaclass__ = Type # Note: any class or object has to have a callerclass attribute for this to work. # That makes it thread - incompatible I guess. callerclass = None # Here is your example code class A(Object): @localmethod def m(self): print 'A.m' def am(self): self.m() class B(A): @localmethod def m(self): print 'B.m' def bm(self): self.m() m = B() m.am() # prints 'A.m' m.bm() # prints 'B.m' # Untested beyond this particular example! -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list