Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 动态函数docstring_Python - Fatal编程技术网

Python 动态函数docstring

Python 动态函数docstring,python,Python,我想编写一个具有动态创建的docstring的python函数。本质上,对于函数func()而言,我希望func.\uuuu doc\uuuu是一个描述符,用于调用自定义\uuu get\uuuu函数,根据请求创建docstring。然后help(func)应返回动态生成的docstring 这里的上下文是编写一个python包,将大量命令行工具包装在现有的分析包中。每个工具都成为一个命名类似的模块函数(通过函数工厂创建并插入到模块名称空间中),函数文档和接口参数通过分析包动态生成。为什么不编写

我想编写一个具有动态创建的docstring的python函数。本质上,对于函数
func()
而言,我希望
func.\uuuu doc\uuuu
是一个描述符,用于调用自定义
\uuu get\uuuu
函数,根据请求创建docstring。然后
help(func)
应返回动态生成的docstring


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

为什么不编写自己的
帮助
函数,而不是搅乱函数

my_global=42

def help(func):
    print('%s: my_global=%s'%(func.func_name,my_global))        

def foo():
    pass

help(foo)

你不能以你想做的方式做你想做的事

从您的描述来看,您似乎可以这样做:

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)
i、 e.创建函数时,预先动态创建文档字符串。 这就是为什么从一个调用到下一个调用,docstring必须是动态的原因吗

假设有,您必须将函数封装在一个类中,使用
\uuuuu call\uuuu
触发操作

但即使这样,你也有问题。当调用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)
不起作用,因为属性是实例,而不是类属性。通过将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__
为了同样的事情。
\uuu doc\uu
属性位于
\u ToolWrapper
类中,需要它来捕获后一种情况。

(Python 3解决方案)

您可以利用Python的duck类型实现动态字符串:

import time

def fn():
    pass

class mydoc( str ):
    def expandtabs( self, *args, **kwargs ):
        return "this is a dynamic strting created on {}".format( time.asctime() ).expandtabs( *args, **kwargs )

fn.__doc__ = mydoc()

help( fn )
注意事项:
这假设
help
函数正在调用
.expandtabs
,以从在Python 3.7中工作的
\uuuu doc\uuuu
对象获取文本。一个更健壮的解决方案将实现其他
str
方法,以便让我们的duck继续像duck一样工作,即使
help
方法发生变化。还请注意,我们的
mydoc
类派生自
str
,这是因为
help
,有点非典型,通过断言
isinstance(thing.\uu doc\uuuuu,str)
来强制输入。与所有解决方案一样,这有点粗糙,但这是否是一个问题在很大程度上取决于整个项目的要求。

我怀疑这是可能的,因为您甚至不能对函数类型进行子类化,更不用说以某种方式使
def
生成您自己类型的对象。我想动态地这样做,因为在分析包中可以为不同的工具设置参数值,并且这些参数会被记住。我希望函数docstring显示该工具的当前参数设置。因此,当你请求“帮助(wrapped_tool)”时,它需要实时查询分析包并创建文档字符串。我还不能评论其他人的帖子(新手等),但我想说,重载help()不是一个很好的解决方案,因为你不能保证在任何地方都可以使用help()将调用。将使用您的版本而不是默认版本。根据我的经验,依赖这种猴子补丁会在以后出现意外的用例时(例如新的文档工具、使用“增强”ipython的用户或IDE中的GUI帮助等)导致难以调试的问题。很好,这就成功了。前两个代码示例正是我在发布问题之前编写的。我同意重载帮助不是一个好主意。只要对猴子补丁说不就行了。我同意@Ian的观点,
help
builtin的重载不是一个好主意,因为你永远不知道它将如何在其他地方使用。但是,可能会有一个改进的实现,它会在自定义实现和默认实现之间包装一个切换。这是一个糟糕的做法,不要这样做。