动态函数docstring

Tom*_*oft 10 python

我想编写一个具有动态创建的文档字符串的python函数.本质上对于一个函数func()我想func.__doc__成为一个调用自定义__get__函数的描述符,根据请求创建docstring.然后help(func)应该返回动态生成的docstring.

这里的上下文是在现有的分析包中编写一个包含大量命令行工具的python包.每个工具都成为一个类似命名的模块函数(通过函数工厂创建并插入到模块命名空间中),通过分析包动态生成函数文档和接口参数.

Ian*_*Ian 11

按照你想要的方式,你无法做你想做的事.

根据您的描述,您似乎可以执行以下操作:

for tool in find_tools():
    def __tool(*arg):
        validate_args(tool, args)
        return execute_tool(tool, args)
    __tool.__name__ = tool.name
    __tool.__doc__ = compile_docstring(tool)
    setattr(module, tool.name, __tool)
Run Code Online (Sandbox Code Playgroud)

即在创建函数时动态创建文档字符串.文档字符串从一次调用到__doc__下一次调用必须是动态的原因吗?

假设有,你必须在一个类中包装你的函数,__call__用来触发动作.

但即便如此,你也遇到了问题.当调用help()来查找docstring时,它会在类而不是实例上调用,所以这样的事情:

class ToolWrapper(object):
    def __init__(self, tool):
        self.tool = tool 
        self.__name__ = tool.name
    def _get_doc(self):
        return compile_docstring(self.tool)
    __doc__ = property(_get_doc)
    def __call__(self, *args):
        validate_args(args)
        return execute_tool(tool, args)
Run Code Online (Sandbox Code Playgroud)

不起作用,因为属性是实例,而不是类属性.您可以通过将文档属性放在元类而不是类本身来使其工作

for tool in find_tools():
    # Build a custom meta-class to provide __doc__.
    class _ToolMetaclass(type):
        def _get_doc(self):
            return create_docstring(tool)
        __doc__ = property(_get_doc)

    # Build a callable class to wrap the tool.
    class _ToolWrapper(object):
        __metaclass__ = _ToolMetaclass
        def _get_doc(self):
            return create_docstring(tool)
        __doc__ = property(_get_doc)
        def __call__(self, *args):
            validate_args(tool, args)
            execute_tool(tool, args)

    # Add the tool to the module.
    setattr(module, tool.name, _ToolWrapper())
Run Code Online (Sandbox Code Playgroud)

现在你可以做到

help(my_tool_name)
Run Code Online (Sandbox Code Playgroud)

并获取自定义文档字符串,或

my_tool_name.__doc__
Run Code Online (Sandbox Code Playgroud)

为了同样的事情.的__doc__属性是在_ToolWrapper类是需要陷阱后者的情况.

  • 我不能评论别人的帖子(新手和所有),但我想说重载help()不是一个很好的解决方案,因为你不能保证任何地方都会调用help()您的版本而不是默认版本.根据我的经验,依赖于那种猴子修补,导致在意外的用例到来时(例如新的文档工具,或具有'增强的'ipython的用户或GUI)的日期难以调试问题帮助IDE,等等). (3认同)