我想编写一个具有动态创建的文档字符串的python函数。从本质上讲,对于一个函数,func()我想func.__doc__成为一个调用自定义__get__函数的描述符,根据要求创建文档字符串。然后help(func)应返回动态生成的文档字符串。
func()
func.__doc__
__get__
help(func)
这里的上下文是编写一个Python包,在现有的分析包中包装大量命令行工具。每个工具都变成了一个类似命名的模块函数(通过函数工厂创建并插入到模块名称空间中),其中函数文档和接口参数是通过分析包动态生成的。
您无法以自己想做的方式去做自己想做的事情。
从您的描述看来,您可以执行以下操作:
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__吗?
__doc__
假设有,您必须将函数包装在一个类中,然后使用它__call__来触发操作。
__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类中是需要捕获后一种情况的。
_ToolWrapper