IPython中被装饰器包装的函数无法显示文档字符串如何解决?
如何让被装饰的函数在IPython中正常显示自身文档字符串?
在IPython中运行以下代码后,执行func_with_wrap?会显示<no docstring>,但func_no_wrap?可以正常展示对应的文档字符串:
def wrap(f): """ wrap docstring """ def wrapped(): return return wrapped @wrap def func_with_wrap(): """ func_with_wrap docstring """ return def func_no_wrap(): """ func_no_wrap docstring """ return
IPython执行输出如下:
In [12]: func_with_wrap? Signature: func_with_wrap() Docstring: <no docstring> File: c:\confidential> Type: function In [13]: func_no_wrap? Signature: func_no_wrap() Docstring: func_no_wrap docstring File: c:\confidential> Type: function
之后尝试了两种修改装饰器的方式:
- 无效写法:
def wrap(f): """ wrap docstring """ def wrapped(): wrapped.__doc__ = f.__doc__ return return wrapped
这种写法下,IPython依然无法显示func_with_wrap的文档字符串。
- 有效写法:
def wrap(f): """ wrap docstring """ def wrapped(): return wrapped.__doc__ = f.__doc__ return wrapped
问题解析与解决方案
问题核心在于:IPython执行?查看文档时,是直接读取函数对象的__doc__属性,不会触发函数调用。
第一种无效写法里,wrapped.__doc__ = f.__doc__写在wrapped函数内部,只有当func_with_wrap(即wrapped)被调用时才会执行赋值,IPython查看文档时不会调用函数,因此读取到的还是wrapped初始的空文档字符串。
而有效写法是在定义完wrapped后、返回它之前,直接将wrapped.__doc__赋值为原函数f的__doc__。装饰器完成对func_with_wrap的替换后,func_with_wrap的__doc__属性已经被正确设置,IPython就能直接读取到原函数的文档字符串。
另外,用Python标准库的functools.wraps装饰器可以更优雅地解决问题,它会自动把原函数的文档字符串、函数名等元信息复制到包装函数上:
import functools def wrap(f): """ wrap docstring """ @functools.wraps(f) def wrapped(): return return wrapped @wrap def func_with_wrap(): """ func_with_wrap docstring """ return
这种写法不仅能保留文档字符串,还能保留原函数的名称、签名等信息,是更规范的装饰器实现方式。
内容的提问来源于stack exchange,提问作者likethevegetable
相关产品推荐
相关产品推荐

