I have a decorator for an object method:
def wrapper(func):
def _wrapper(self, *a, **kw):
print(self.foo)
return func(self, *a, **kw)
return _wrapper
class Bar:
foo = 1
@wrapper
def baz(self):
print(2)
# This works as expected :)
In [2]: Bar().baz()
1
2
I want to add another level of wrapping around this to allow parameters:
def wrapper(bla):
def _wrapper(func):
def __wrapper(self, *a, **kw):
print(self.foo + bla)
return func(self, *a, **kw)
return __wrapper
return _wrapper
class Bar:
foo = 1
@wrapper(1)
def baz(self):
print(2)
# which also works great
In [4]: Bar().baz()
2
2
Now, what I want to be able to do is pass a self
attribute as a wrapper parameter, i.e. call it with something like this
class Bar:
def __init__(self):
self._foo = 1
@wrapper(self._foo)
def baz(self):
pass
I see 2 options:
self._foo
globalself._foo
, and make the decorator access self._foo
Both are bad. (global can be changed from another place without my knowledge, and making the decorator access self._...
means the decorator knows the class it operates on)
Is there a good way to do this?
This example works just fine (You can pick _foo
or _bar
) and the wrapper itself knows nothing of Bar
nor its members:
def wrapper(bla):
def _wrapper(func):
def __wrapper(self, *a, **kw):
print(getattr(self, bla))
return func(self, *a, **kw)
return __wrapper
return _wrapper
class Bar:
def __init__(self):
self._foo = 1
self._bar = 2
@wrapper("_bar") # pick _foo or _bar here
def baz(self):
pass
Bar().baz()
Output: 2
The wrapper
decorator can be located in another module, or as part of a library and Bar
as the client will be unknown to the decorator.