需求:
在函数对象中保存着一些函数的元数据,例如:
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__',)