Metaclass with name overloading.

Lenard Lindstrom len-1 at telus.net
Mon Sep 27 23:07:06 EDT 2004


Carlos Ribeiro <carribeiro at gmail.com> writes:

> On Mon, 27 Sep 2004 21:23:14 GMT, Lenard Lindstrom <len-1 at telus.net> wrote:
> > Carlos Ribeiro <carribeiro at gmail.com> writes:
> > > <sample code snip>
> > > The problem is that the methods were not bound to the instance. Adding
> > > individual names to each method won't work, because it'll not bind the
> > > references stored in the overload_list. I thought about using a
> > > closure or curry type of solution, but that's something that I still
> > > don't understand very well. Any tips?
> > > 
> > Here is my take on decorator overloaded. I implement OverloadedFunction
> > as a descriptor. It supports method binding.
> 
> That's what I was missing. I've read about descriptors last week, but
> didn't had the time to get a hand at it. It's interesting. My
> development machine is still using 2.3 -- I don't know if this
> descriptor fancy stuff would work here... *btw, that's why my original
> snippet didn't use the new syntax to call the decorator).
> 
Descriptors were introduced in 2.2. This version works with 2.2 and
up. The previous example only worked with the new decorator syntax.

import sys

class OverloadedFunction(object):
    class BoundMethod:
        def __init__(self, functions, instance, owner):
            self.bm_functions = functions
            self.bm_instance = instance
            self.bm_owner = owner
        def __getitem__(self, index):
            return self.bm_functions[index].__get__(self.bm_instance,
                                                    self.bm_owner)
    def __init__(self, functions):
        self.of_functions = functions
    def __get__(self, instance, owner):
        return self.BoundMethod(self.of_functions,
                                instance,
                                owner)

def overloaded(func):
    listattr = '_%s_functions_' % func.__name__
    attrs = sys._getframe(1).f_locals
    try:
        functions = attrs[listattr]
        functions.append(func)
    except KeyError:
        functions = [func]
        attrs[listattr] = functions
    return OverloadedFunction(functions)

# Test case:
class blob:
    def __init__(self, member):
        self.member = member
    def f(self):
        return "f 0: member=%s" % self.member
    f = overloaded(f)
    def f(self, s):
        return "f 1: member=%s, s=%s" % (self.member, s)
    f = overloaded(f)

b=blob("XXX")
print b.f[0]()
print b.f[1]("Yet another f")

> I think that this code is now Cookbook-ready. Any comments?
>
Unfortunately it does not work as is with the staticmethod and
classmethod wrappers since these do not define either a
__name__ or fn_name attribute. And it takes an extra bit of
convolution to get at the functions wrappered by these objects.
There are more callables in Python than your philosophy can
imagine. And each requires its own kind of introspection.

Lenard Lindstrom
<len-l at telus.net>




More information about the Python-list mailing list