Instance method decorator garbage collection problem

John Reid j.reid at mail.cryst.bbk.ac.uk
Wed Jun 23 08:56:34 EDT 2010



Thomas Jollans wrote:
>> The InstanceCounted.count is 1 at the end. If I omit the call to
>> "self.method = print_exception_decorator(self.method)" then the instance
>> count goes down to 0 as desired. I thought that the decorator might be
>> holding a reference to the instance through the bound method, so I added
>>  the __del__() but it doesn't fix the problem.
> 
> Adding __del__ like this does "fix the problem", but it introduces a new
> one: lacking a call to super().__del__, you simply don't decrement the
> instance count.

Now that's a good point! I've added super().__del__ but the problem 
remains for some reason. My A class now looks like:

class A(InstanceCounted):
     "A class that I want to decorate a method on."
     def __init__(self):
         super(A, self).__init__()
         self.method = print_exception_decorator(self.method)

     def __del__(self):
         super(A, self).__del__()
         del self.method

     def method(self):
         pass


Did you try this?

> 
> To decorate a method, you'd best just decorate it normally. I doubt your
> technique will work anyway, as the function returned by the decorator
> isn't bound to the object, you'd need to pass one self reference
> implicitly, which is then thrown away.

Looking at the original post, I had included an extra "self" in the 
argument list

def decorator(self, *args, **kwds):

should have been

def decorator(*args, **kwds):


With this correction my method decorates instance methods on objects 
successfully although I don't know why the garbage collection isn't working.



> 
> simply,
> 
> def exc_decor(fn):
>     @functools.wraps(fn)
>     def wrapper(*args, **keywords):
>         try:
>             return fn(*args, **keywords):
>         except:
>             #...
>             raise
>     return wrapper
> 
> class X(...):
>    @exc_decor
>    def foo(self, arg):
>       pass
> 
> (if targeting pre-decorator Python, the code would look different of course)
> 
> This way, the function itself is decorated, and the function returned by
> the decorator is bound to the object. It'll just work as expected, no
> trickery required.

Thanks for this. I remember having some problems decorating instance 
methods in the past which is why I started doing it as in the original 
post. Your method seems just fine though.

Thanks,
John.




More information about the Python-list mailing list