I'm using python 2.4 unfortunately (not by choice) so none of the wonderful things added in 2.5 (such as functools) can help me

I want to wrap a function, but make it so that when you do help(wrapper) it appears to be the function that it wraps

I've partially achieved this by doing

def a():
    """a's docstring"""
    pass

def wrapper():
    a() 
wrapper.func_name = a.func_name #or should this use __name__ ?
wrapper.func_doc = a.func_doc #or should this use __doc__ ?

Now doing help(wrapper) displays a for the function name and a's docstring. Besides feeling hacky, this doesn't cover the function parameters in a case such as:

def b(x, y, z): 
    return a+b+c #or whatever

def wrapper(*args, **kwargs):
    #do something with the arguments
    return b(*args **kwargs)

help(wrapper) causes this to appear as b(*args, **kwargs) which isn't what I want, obviously. There doesn't seem to be any attribute in dir(a) that can help me unless it's nested somewhere.


EDIT: if you can use pypi, look at the decorator module which helps with this.

有帮助吗?

解决方案

Use functools.wraps.

Note that it doesn't fake out the argument specification. You probably could do that (using inspect.getargspec to work out the argument specification of foo and then hacking bar), but it's not conventional.


EDIT: Since you're using Python 2.4, you'll have to re-implement the functionality of functools.wraps. Fortunately it is actually pretty simple; it just copies over the attributes __module__, __name__ and __doc__, and then updates the wrapper's __dict__ with the wrapped function's __dict__. So you could do:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)

def update_wrapper(wrapper,
                   wrapped,
                   assigned = WRAPPER_ASSIGNMENTS,
                   updated = WRAPPER_UPDATES):
    for attr in assigned:
        setattr(wrapper, attr, getattr(wrapped, attr))
    for attr in updated:
        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
    # Return the wrapper so this can be used as a decorator via partial()
    return wrapper

def wraps(wrapped,
          assigned = WRAPPER_ASSIGNMENTS,
          updated = WRAPPER_UPDATES):
    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)

(FYI this is the actual source code of functools.wraps.)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top