A decorator is just a function that does something with another function. So, technically, you can put the required code directly under the foo method, and then, technically, you would change foo without using a decorator, but that would be a terrible mess.
The easiest way to do what you want is to make a decorator that takes a second function ( bar in this case) as an argument so that it knows which signature should copy. The class code would then look something like this:
class Blah(object): @copy_argspec(bar) def foo(self, *args, **kwargs): """ a docstr """ result = bar(*args, **kwargs) result = result**2
You must have the bar specified earlier, and not after the class.
.
.
.
,, Time passes.,.
.
.
Well, fortunately, I found an old decorator that I could fit.
help(Blah.foo) looks like this:
Help on method foo in module __main__: foo(self, *args, **kwargs) unbound __main__.Blah method a docstr
and after registration looks like this:
Help on method foo in module __main__: foo(self, x, y, z=1, q=2) unbound __main__.Blah method a more useful docstr, saying what x,y,z,q do
Here is the decorator I used:
import inspect class copy_argspec(object): """ copy_argspec is a signature modifying decorator. Specifically, it copies the signature from `source_func` to the wrapper, and the wrapper will call the original function (which should be using *args, **kwds). The argspec, docstring, and default values are copied from src_func, and __module__ and __dict__ from tgt_func. """ def __init__(self, src_func): self.argspec = inspect.getargspec(src_func) self.src_doc = src_func.__doc__ self.src_defaults = src_func.func_defaults def __call__(self, tgt_func): tgt_argspec = inspect.getargspec(tgt_func) need_self = False if tgt_argspec[0][0] == 'self': need_self = True name = tgt_func.__name__ argspec = self.argspec if argspec[0][0] == 'self': need_self = False if need_self: newargspec = (['self'] + argspec[0],) + argspec[1:] else: newargspec = argspec signature = inspect.formatargspec( formatvalue=lambda val: "", *newargspec )[1:-1] new_func = ( 'def _wrapper_(%(signature)s):\n' ' return %(tgt_func)s(%(signature)s)' % {'signature':signature, 'tgt_func':'tgt_func'} ) evaldict = {'tgt_func' : tgt_func} exec new_func in evaldict wrapped = evaldict['_wrapper_'] wrapped.__name__ = name wrapped.__doc__ = self.src_doc wrapped.func_defaults = self.src_defaults wrapped.__module__ = tgt_func.__module__ wrapped.__dict__ = tgt_func.__dict__ return wrapped