Why is class decorator on method loosing self?

George Sakkis george.sakkis at gmail.com
Tue Nov 21 14:55:33 EST 2006


George Sakkis wrote:

> I don't think you can make it work without resorting to metaclass
> magic. At the point of decoration min_max is still a function, not a
> method, because class Foo has not been created yet. Here's a way to do
> it with a custom metaclass; whether you really want to do it is a
> different matter:

An improvement to my previous hack: leave memoize as is in the cookbook
(extending decoratorargs) and add two lines to decoratorargs:

# This would usually be defined elsewhere
class decoratorargs(object):
    def __new__(typ, *attr_args, **attr_kwargs):
        def decorator(orig_func):
            self = object.__new__(typ)
            self.__init__(orig_func, *attr_args, **attr_kwargs)
            if callable(self):
                self._customize = lambda cls: MethodType(self, None,
cls)
            return self
        return decorator

Now you don't need memoizefunction and memoizemethod, but you still
need the customized metaclass (changed __customize to _customize; name
turns to a PITA sooner or later):

class CustomizeMeta(type):
    def __init__(cls, name, bases,dict):
        for attr,val in dict.iteritems():
            if hasattr(val, '_customize'):
                setattr(cls, attr, val._customize(cls))


#==== examples =============================================

@memoize(3)
def fib(n):
    return (n > 1) and (fib(n - 1) + fib(n - 2)) or 1

class Foo(object):
    __metaclass__ = CustomizeMeta

    def __init__(self, i): self._i = i

    def banner(self):
        print "Testing method"

    @memoize(3)
    def min_max(self, sequence):
        self.banner()
        return min(sequence), max(sequence)
 
foo = Foo()
print foo.min_max([9,7,5,3,1])


George




More information about the Python-list mailing list