Reputation: 2311
I know how to use locally defined functions in decorators. I do this in decorator1
below.
However, I don't find it very clean, and I experienced pickling problems with it.
I would thus like my decorator to return a callable object. However, I am running into problems: If I execute the following code
def decorator1(f):
def wrapped(*args,**kwargs):
print(f,' is being called with ',args,kwargs)
return f(*args,**kwargs)
return wrapped
def decorator2(f):
return Wrapped(f)
class Wrapped():
def __init__(self,f):
self.f=f
def __call__(self,*args,**kwargs):
print(self.f,' is being called with ',args,kwargs)
return self.f(*args,**kwargs)
class A():
@decorator1
def foo1(self,x):
return x+1
@decorator2
def foo2(self,x):
return x+1
a=A()
a.foo1(0)
a.foo2(0)
I get
<function A.foo1 at 0x7efe64641f28> is being called with (<__main__.A object at 0x7efe65b3b3c8>, 0) {}
<function A.foo2 at 0x7efe6464c0d0> is being called with (0,) {}
Traceback (most recent call last):
File "/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py", line 28, in <module>
a.foo2(0)
File "/home/wolfersf/Dropbox/Professional/Projects/swutil/swutil/test.py", line 15, in __call__
return self.f(*args,**kwargs)
TypeError: foo2() missing 1 required positional argument: 'x'
It seems that a
is not passed in *args
of <Wrapped_instance>.__call__
.
I would have thought that a.foo2(0)
translates to <a.foo2>(a,0)
translates to <Wrapped_instance>(a,0)
translates to <Wrapped_instance>.__call__(a,0)
translates to <<Wrapped_instance>.__call__>(<Wrapped_instance>,a,0)
What am I doing wrong?
Upvotes: 3
Views: 1516
Reputation: 2311
Overwriting __get__
as below does the job, though I am still not sure exactly why my original attempt failed.
class Wrapped():
def __init__(self,f):
self.f=f
def __call__(self,*args,**kwargs):
print(self.f,' is being called with ',args,kwargs)
return self.f(*args,**kwargs)
def __get__(self,obj,type=None):
return functools.partial(self,obj)
Upvotes: 2