Python Study Notes 2-functools.wraps decorators, functools. wraps
Wraps has no practical application, but is used to solve the problem that the attribute of the function pointed to by the original function name caused by the decorator changes. The decorator has decorated the function func, in this case, func does not point to the real func, but to the decorated function in the decorator.
import sysdebug_log = sys.stderrdef trace(func): if debug_log: def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res return callf else: return func@tracedef square(x): """Calculate the square of the given number.""" return x * x Here, square actually points to cballs. You can use help (square) or square. _ name _ to check it. After square is decorated, the function is actually another function (function attributes such as the function name will change). If wraps is used for modification
def trace(func): if debug_log: @functools.wraps(func) def callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res return callf else: return func
In this case, the attribute of square decorated with trace will not change. You can help (square) to see it.
Cause: we translate the wraps decoration Code as follows, which is equivalent:
def trace(func): if debug_log: def _callf(*args, **kwargs): """A wrapper function.""" debug_log.write('Calling function: {}\n'.format(func.__name__)) res = func(*args, **kwargs) debug_log.write('Return value: {}\n'.format(res)) return res callf = functools.update_wrapper(_callf, wrapped = func,assigned = functools.WRAPPER_ASSIGNMENTS,updated = functools.WRAPPER_UPDATES) return callf else: return func
Update_wrapper does a very simple job, that is, some attributes of function objects (such as square) represented by the wrapped parameter (such as: __name _ and _ doc __) override the corresponding attributes of the function objects represented by the wrapper parameter (for example, callf, where callf simply calls the square function, so callf is a wrapper function of square.
Therefore, in this example, after you use the wraps modifier to "Decorate" callf, the attributes of callf, such as _ doc _ and _ name _, are exactly the same as those of the Function square whose trace is to be "decorated.