Metaclass with name overloading.
bokr at oz.net
Mon Sep 27 22:56:04 CEST 2004
On Mon, 27 Sep 2004 19:11:14 +0200, aleaxit at yahoo.com (Alex Martelli) wrote:
>Thomas Heller <theller at python.net> wrote:
>> It won't work for ordinary attributes, but for overloading methods you
>> should be able to play some tricks with decorators and sys._getframe().
>Great idea... love it!!! To clarify it a bit for people who may not be
>as familiar with internals as Mr Heller...: a decorator 'sees' the
>method it's decorating "at once", so it doesn't matter if that method's
>name later gets trampled upon... as long as the decorator can stash the
>original away somewhere, and the frame in which the class body is
>executing is just the right 'somewhere'.
>A code snippet may be clearer than words...:
>import sys, itertools
>_ignore_method = object()
> d = sys._getframe(1).f_locals
> n = '__overloaded__%s__%%d' % f.func_name
> for i in itertools.count():
> nx = n % i
> if nx in d: continue
> d[nx] = f
> return _ignore_method
> @ overloaded
> def f(self): return 'first f'
> @ overloaded
> def f(self): return 'second f'
>so, class blop doesn't really have an 'f' (it does have it in the
>__dict__, but it's a dummy '_ignore_method' entry with a suitable custom
>metaclass would easily prune!-) but has __overloaded__f__0 and
>__overloaded__f__1 methods (which, again, a suitable custom metaclass
>could do whatever wonders with!-).
>For overload purposes, you might have the decorator actually take as
>arguments some _types_ and record them so that the metaclass can arrange
>for the dispatching based on actual-argument types...
>If you bletch at having to decorate each overloaded version with
>'@overloaded', consider C# basically requires that "just BECAUSE",
>without even having a good excuse such as "we need to do it that way due
>to Python's semantics"...;-)
If there were a way to make a local bare name access work like a property
or other descriptor, by designating such names suitably, then def f...
could trigger the setter of an f property and that could do whatever.
It might be interesting for a function closure variables also, but here
we are talking about class bodies. Here is a straw man:
f = property(fget, fset)
def f(self): return 'first f'
def f(self): return 'second f'
This effectively considers the local namespace as the attribute name space
of _something_, presumably an internal instance of some synthesized Localspace class,
let's say localspace = LocalspaceType()() -- IOW a fresh class as well as its instance,
so as to cut off base class searching and not to have surprising sharing.
Optimization is for later ;-)
The localdesc suite would cause assignment to be via type(localspace).__dict__.__setitem__
whereas normal local names would be evaluated by get/setattr(localspace, barename) and
thus trigger descriptors if present. Note that all bindings including from
def and class as well as ordinary variables could be intercepted by descriptors.
sys._getframe(level).f_locals would presumably be a special proxy object instead of a dict
when there is a localdesc: suite in the body, so that it could decide whether names
are descriptors or ordinary. Otherwise it could remain the usual dict and not get
a performance hit, I suppose.
More information about the Python-list