Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Why is class decorator on method loosing self?

Reply
Thread Tools

Why is class decorator on method loosing self?

 
 
c james
Guest
Posts: n/a
 
      11-21-2006
I want to use the LRU decorator posted at
http://aspn.activestate.com/ASPN/Coo.../Recipe/498110
on a class method. However, it complains about missing arguments. The
missing argument is `self`. I could use @classmethod but what I really
need is an instance method. I don't see how and was hoping someone else
might know the way.

Here is an example with taking that recipe as lru.py

import lru

class Foo(object):
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])


Traceback (most recent call last):
....
File "lru.py", line 48, in __call__
value = self.func(*args, **kwargs)
TypeError: min_max() takes exactly 2 arguments (1 given)

 
Reply With Quote
 
 
 
 
George Sakkis
Guest
Posts: n/a
 
      11-21-2006
c james wrote:

> I want to use the LRU decorator posted at
> http://aspn.activestate.com/ASPN/Coo.../Recipe/498110
> on a class method. However, it complains about missing arguments. The
> missing argument is `self`. I could use @classmethod but what I really
> need is an instance method. I don't see how and was hoping someone else
> might know the way.
>
> Here is an example with taking that recipe as lru.py
>
> import lru
>
> class Foo(object):
> 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])
>
>
> Traceback (most recent call last):
> ...
> File "lru.py", line 48, in __call__
> value = self.func(*args, **kwargs)
> TypeError: min_max() takes exactly 2 arguments (1 given)



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:

First off, remove the decoratorargs class and have memoize inherit from
object:

class memoize(object):
# class body stays the same

Then add the following:


# this is general enough to be moved to a separate module
class CustomizeMeta(type):
def __init__(cls, name, bases,dict):
for attr,val in dict.iteritems():
if hasattr(val, '__customize'):
setattr(cls, attr, getattr(val,'__customize')(cls))


def memoizefunction(*args, **kwds):
return lambda func: memoize(func, *args, **kwds)


def memoizemethod(*args, **kwds):
from types import MethodType
def wrapper(func):
func.__customize = lambda cls: \
MethodType(memoize(func,*args,**kwds), None, cls)
return func
return wrapper

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

@memoizefunction(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"

@memoizemethod(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

 
Reply With Quote
 
 
 
 
c james
Guest
Posts: n/a
 
      11-21-2006
If I am reading this correctly you, are rebinding min_max in
CustomizeMeta using '__customize' as the attribute to identify the
member to work on.

Thank you. I think you are right, this is probably the best way to
implement what I intend for caching resource intensive processing.

to 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:
>


> George
>


 
Reply With Quote
 
George Sakkis
Guest
Posts: n/a
 
      11-21-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

 
Reply With Quote
 
George Sakkis
Guest
Posts: n/a
 
      11-21-2006
George Sakkis wrote:

> 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):


There was supposed to be a "mangling" after "name" (see, it's hard to
even spell it out correctly, let alone use it <wink>).

George

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Determining if a function is a method of a class within a decorator David Hirschfield Python 2 07-01-2009 12:50 AM
why a class can't access protected method from another class in thesame package,the method is interited from the ohtner class from differntpackage? junzhang1983@gmail.com Java 3 01-28-2008 02:09 AM
How to add a Decorator to a Class Method gregpinero@gmail.com Python 6 11-20-2007 07:04 PM
Why doesnt __getattr__ with decorator dont call __get_method in decorator glomde Python 5 03-29-2007 02:48 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM



Advertisments