Metaclass with name overloading.

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


Carlos Ribeiro <carribeiro at gmail.com> writes:

> On Mon, 27 Sep 2004 19:11:14 +0200, Alex Martelli <aleaxit at yahoo.com> wrote:
> > 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!-).
> 
> The decorator could play it safe, and at the same time, return
> something like the original poster expects. Upon decoration the
> following would happen:
> 
> 1) store the newly declared object in the list __overloaded__<$name>.
> 
> 2) return a new object (to be bound to the <$name>), where
> <$name>.__call__ would return __overloaded__<$name>[-1]; and
> f.__iter__ would return an iterator for all declaration in the order
> they appear.
> 
> I did it as follows; it _almost_ works (which really means it's
> broken), because there's a catch that I was not able to solve:
> 
> ------------
> import sys, itertools
> 
> class OverloadedFunction:
>     def __init__(self):
>         self.overload_list = []
>     def __iter__(self):
>         for item in self.overload_list:
>             yield item
>     def __getitem__(self, index):
>         return self.overload_list[index]
>     def __call__(self, *args, **kw):
>         return self.overload_list[-1](*args, **kw)
>     def append(self, f):
>         self.overload_list.append(f)
> 
> def overloaded(f):
>     d = sys._getframe(1).f_locals
>     n = '__overloaded__%s' % f.func_name
>     #ofl = getattr(d, n, OverloadedFunction())
>     if n in d:
>         print "achou"
>         ofl = d[n]
>     else:
>         print "não achou"
>         ofl = OverloadedFunction()
>     print "<",ofl.overload_list,">", d, n
>     ofl.append(f)
>     d[n] = ofl
>     return ofl
> 
> class blop:
>    def f(self): return 'first f'
>    f = overloaded(f)
> 
>    def f(self): return 'second f'
>    f = overloaded(f)
> 
> print blop.__dict__
> # there's a catch -- methods were not bound to the instance
> # so I need to pass the 'self' parameter manually
> b = blop()
> print blop.f(b)
> print blop.f[0](b)
> print blop.f[1](b)
> 
> 
> 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.

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):
        self.of_functions = []
    def addFunction(self, func):
        self.of_functions.append(func)
    def __get__(self, instance, owner):
        return self.BoundMethod(self.of_functions,
                                instance,
                                owner)

def overloaded(func):
    try:
        olf = sys._getframe(1).f_locals[func.__name__]
    except KeyError:
        olf = OverloadedFunction()
    olf.addFunction(func)
    return olf

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

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

---- Output ---

f 0: member=XXX
f 1: member=XXX, s=Yet another f


Lenard Lindstrom
<len-l at telus.net>



More information about the Python-list mailing list