Вы не можете делать то, что вы хотите сделать, так, как вы хотите это сделать.
Из вашего описания кажется, что вы могли бы сделать что-то вроде этого:
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)
не будет работать, поскольку свойства являются экземплярами, а не атрибутами класса,Вы можете заставить свойство doc работать с метаклассом, а не с самим классом
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
необходимо для захвата последнего случая.