如何为被装饰的函数保存元数据?

需求:
在函数对象中保存着一些函数的元数据,例如:
f.name:函数的名字
f.doc:函数文档字符串
f.module:函数所属模块名
f.dict:函数的属性字典
f.defaults:默认参数元组
.....
我们在使用装饰器后,再访问上面这些属性访问时,看到的是内部包裹函数的元数据,原来函数的元数据便丢失了,应该如何解决 ?

思路:
使用标准库中的funtools中的装饰器wraps装饰内部包裹函数,可以制定将原函数的某些属性,更新到包裹函数上面

代码:

from functools import update_wrapper,wraps

def my_decorator(func):
    @wraps(func) # 等价于update_wrapper(wrap,func)
    def wrap(*args,**kwargs):
        '''某种功能包裹函数'''
        # 此处实现某种功能
        # ...

        return func(*args,**kwargs)
    # update_wrapper(wrap,func)
    return wrap

@my_decorator
def xxx_func(a,b):
    '''
    xxx_func函数文档
    ...
    '''
    pass

print(xxx_func.__name__)
print(xxx_func.__doc__)

=========================================

>>> def f():
...     '''fuction f'''
...     pass
... 
... f.__name__
... f.__name__
... print(f.__name__)
... f.__module__
... 
... 
f
'__main__'
>>> 
>>> def f():
...     '''function f'''
...     pass
... 
... 
>>> f.__name__
'f'
>>> f.__module__
'__main__'
>>> from random import randint
>>> randint.__module__
'random'
>>> f.__doc__
'function f'
>>> f?
Signature: f()
Docstring: function f
File:      ~/python_study/<ipython-input-3-a10bb6a09581>
Type:      function
>>> def f(a:int,b:int) -> int:
...     pass
... 
... 
>>> f.__annotations__
{'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}
>>> def f(a,b=1,c=[]):
...     pass
... 
... 
>>> f.__defaults__
(1, [])
>>> def f(a): # 闭包
...     return lambda n: a ** n
... 
... 
>>> g = f(3)
>>> g(4)
81
>>> g.__closure__
(<cell at 0x7f7002d9be28: int object at 0x559184504360>,)
>>> c = g.__closure__[0]
>>> c.cell_contents
3
>>> from functools import WRAPPER_ASSIGNMENTS
>>> WRAPPER_ASSIGNMENTS
('__module__', '__name__', '__qualname__', '__doc__', '__annotations__')
>>> from functools import WRAPPER_UPDATES
>>> WRAPPER_UPDATES
('__dict__',)
原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13957692.html