I’m trying to write a decorator that works like @property, but running into some problems.
class Dec(object):
def __init__(self, fn):
self._fn = fn
self._before = None
@property
def before(self)
return self._before
@before.setter
def before(self, fn):
self._before = fn
def __call__(self, *args, **kwargs):
self._before(*args, **kwargs)
self._fn(*args, **kwargs)
def withbefore(fn):
return Dec(fn)
Its a simple chaining decorator. The @property/@.setter syntax is exactly what I’m trying to clone.
This works:
@withbefore
def foo():
...
@foo.before
def beforefoo():
...
But on a class it doesn’t:
class Weee(object):
@withbefore
def do_stuff(self):
pass
@do_stuff.before
def before_do_stuff(self):
pass
It raises an import error.
TypeError: 'NoneType' object is not callable
How can i correctly emulate @property/.{setter,getter,deleter} ?
Actually, it raises a TypeError.
Anyway, I got the same error when running your decorator with functions, too. It happens because, when you decorate a function with
@foo.before, it will call theself._beforefunction with the decorated function as parameter. Sinceself._beforeisNone, it will raise the error.There are various solutions for it. My favorite is to set a different default value to
self._before– a function which will set theself._beforevalue:Of course, this function should not be called when the
Decobject is called so we change the__call__method: