一尘不染

动态函数文档字符串

python

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

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


阅读 173

收藏
2021-01-20

共1个答案

一尘不染

您无法以自己想做的方式去做自己想做的事情。

从您的描述看来,您可以执行以下操作:

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)

即在创建函数时动态地预先创建文档字符串。是从一个调用到另一个调用都必须使文档字符串动态化的原因__doc__吗?

假设有,您必须将函数包装在一个类中,然后使用它__call__来触发操作。

但是即使那样,您仍然有问题。当调用help()查找文档字符串时,它是在类而不是实例上调用的,所以这种事情:

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)

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

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())

现在你可以做

help(my_tool_name)

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

my_tool_name.__doc__

对于同一件事。该__doc__属性在_ToolWrapper类中是需要捕获后一种情况的。

2021-01-20