Class method decorator with self arguments?
Yes. Instead of passing in the instance attribute at class definition time, check it at runtime:
def check_authorization(f): def wrapper(*args): print args[0].url return f(*args) return wrapperclass Client(object): def __init__(self, url): self.url = url @check_authorization def get(self): print 'get'>>> Client('http://www.google.com').get()http://www.google.comget
The decorator intercepts the method arguments; the first argument is the instance, so it reads the attribute off of that. You can pass in the attribute name as a string to the decorator and use getattr
if you don't want to hardcode the attribute name:
def check_authorization(attribute): def _check_authorization(f): def wrapper(self, *args): print getattr(self, attribute) return f(self, *args) return wrapper return _check_authorization
A more concise example might be as follows:
#/usr/bin/env python3from functools import wrapsdef wrapper(method): @wraps(method) def _impl(self, *method_args, **method_kwargs): method_output = method(self, *method_args, **method_kwargs) return method_output + "!" return _implclass Foo: @wrapper def bar(self, word): return wordf = Foo()result = f.bar("kitty")print(result)
Which will print:
kitty!
from re import searchfrom functools import wrapsdef is_match(_lambda, pattern): def wrapper(f): @wraps(f) def wrapped(self, *f_args, **f_kwargs): if callable(_lambda) and search(pattern, (_lambda(self) or '')): f(self, *f_args, **f_kwargs) return wrapped return wrapperclass MyTest(object): def __init__(self): self.name = 'foo' self.surname = 'bar' @is_match(lambda x: x.name, 'foo') @is_match(lambda x: x.surname, 'foo') def my_rule(self): print 'my_rule : ok' @is_match(lambda x: x.name, 'foo') @is_match(lambda x: x.surname, 'bar') def my_rule2(self): print 'my_rule2 : ok'test = MyTest()test.my_rule()test.my_rule2()
ouput: my_rule2 : ok