Reputation: 2396
When I try to decorate a method with arguments in the decorate it gives me a self
is not defined. if instead I change assign val
as a class variable and use MyCls.val
it now gives me MyCls is not defined! How do I decorate my mehtod?
def dodecorate(VAL):
def decorate(func):
def wrapped(*args,**kwargs):
res = func(*args,**kwargs)
if res == VAL:
res = "one"
return res
return wrapped
return decorate
class MyCls(object):
def __init__(self):
self.val = 1
@dodecorate(VAL = self.val)
def onefrom1(self, x):
return x
EDIT The above was an abstraction I invented to represent the original. Here is the actual code.
def retry_on_invalid_schema(MAX_RETRIES):
def retrier(func):
def wrapped(*args, **kwargs):
tries = 0
res = None
while tries < MAX_TRIES:
try:
res = func(*args, **kwargs)
assert res.has_key('by')
assert res.has_key('id')
break
except AssertionError:
res = None
time.sleep(2**tries)
tries += 1
continue
return res
return wrapped
return retrier
class Base(object):
def __init__(self):
self.MAX_RETRIES = 3
@retry_on_invalid_schema(MAX_RETRIES = self.MAX_RETRIES)
def _get_api_response(self, uri):
return json.loads(self._get(uri))
def _get(self, uri):
return requests.get(uri).text
Upvotes: 0
Views: 91
Reputation: 122091
If you want to use an existing decorator function on an instance method, note that you can redefine instance methods in __init__
, calling the decorator directly rather than using the @
syntax:
class MyCls(object):
def __init__(self):
self.val = 1
self.onefrom1 = dodecorate(self.val)(self.onefrom1)
def onefrom1(self, x):
return x
In use:
>>> a = MyCls()
>>> for x in range(3):
print a.onefrom1(x)
0
one
2
Upvotes: 1
Reputation: 11269
Instead of trying to pass val
to the decorator, you can just access it via the instance. self
contains the current instance and is passed to the wrapped method in the decorator, so you can access that in the decorator as the first argument.
def decorate(func):
def wrapped(instance, *args, **kwargs):
res = func(instance, *args, **kwargs)
if res == instance.val:
res = "one"
return res
return wrapped
class MyCls(object):
def __init__(self):
self.val = 1
@decorate
def onefrom1(self, x):
return x
c = MyCls()
print c.onefrom1(1)
print c.onefrom1(2)
output
one
2
Upvotes: 0