There are two ways to invoke decorators: 1) by passing decorator function/class
class Foo(object):
def __init__(self):
self.x = 1
@foo_decorator
def bar(self, x):
return self.x + x
or 2) by passing return value of the decorator function/class instance.
class Foo(object):
def __init__(self):
self.x = 1
@foo_decorator("args")
def bar(self, x):
return self.x + x
The question is: how do I get the decorator to work for both cases, given that I need to implement the decorator using class-based method?
An example of such implementation would be
import functools
class FooDecorator(object):
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
self.f = args[0]
functools.update_wrapper(self, args[0])
else:
self.f = None
def __call__(self, *args, **kwargs):
if self.f is not None:
return self.f(*args, **kwargs)
else:
assert len(args) >= 1 and callable(args[0])
f = args[0]
self.f = f
functools.update_wrapper(self, f)
return self
foo_decorator = FooDecorator
However, testing this simple implementation using the following code yields some errors:
class Foo1(object):
def __init__(self):
self.x = 1
@foo_decorator
def bar(self, x):
return self.x + x
class Foo2(object):
def __init__(self):
self.x = 1
@foo_decorator("args")
def bar(self, x):
return self.x + x
Foos = [Foo1, Foo2]
for i in range(2):
print(Foos[i].__name__)
f = Foos[i]()
print(f.bar(10))
Traceback (most recent call last):
File "python", line 47, in <module>
File "python", line 13, in __call__
TypeError: bar() missing 1 required positional argument: 'x'
This has been tested on both python 2.7 and 3.5.
Any help is appreciated. Note that I have already thoroughly searched the entire web, and have already read the following articles on the subject:
- Graham Dumpleton: How you implemented your Python decorator is wrong.
decorator
package on PyPI documentation
Also note that decorator
package does not support the second method for incurring decorators (pre-initializing decorator objects) to my knowledge.