Reputation: 4449
First of all I don't know if this is the right approach. I want to write a decorator class that will be used with methods of other class. Before running the method I'd like to check if all required class variables are initialized. The ideal case would be something similar to this:
class Test(object):
def __init__(self, f):
self.f = f
# some magic
def __call__(self):
self.f.magically_get_variable(required)
# do some checks and execute method or throw an exception
class Data(object):
def __init__(self, a, b):
self.a = a
@test
def sum(self):
required('self.a', 'self.b')
return self.a + self.b
If this is not the way it should be done please advise me how to do it properly.
Upvotes: 0
Views: 211
Reputation: 882123
If you insist on checking before the decorated method's body starts, the following is one reasonable way to do it...:
import functools
class test(object):
def __init__(self, requiredvars):
self.reqs = requiredvars.split()
def __call__(self, f):
@functools.wraps(f)
def wrapper(wself, *a, **k):
missing = set()
for v in self.reqs:
if not hasattr(wself, v):
missing.add(v)
if missing:
msg = 'missing fields: %s' % ','.join(sorted(missing))
raise valueerror, msg
return f(wself, *a, **k)
return wrapper
class data(object):
def __init__(self, a, b):
self.a = a
@test('a b')
def sum(self):
return self.a + self.b
d = data(23, 42)
d.sum()
This emits, as you apparently desire,
Traceback (most recent call last):
File "rev.py", line 29, in <module>
d.sum()
File "rev.py", line 16, in wrapper
raise ValueError, msg
ValueError: Missing fields: b
Upvotes: 0
Reputation: 116247
I'd say decorators are a bit unfit here for the purpose of checking if a variable exists.
Think about what you're planning to do if the required variables are not supplied: raise an exception (it's in your comment).
I'd say (based on the code above):
def sum(self):
return self.a + self.b
And let it fail if self.a or self.b is not supplied (it will raise a NameError
exception, you can catch that if you like, and you could raise your own then if you want.)
Upvotes: 1