如何使用重载/调度装饰器记录 Python 函数? [英] How to document Python functions with overload/dispatch decorators?

查看:59
本文介绍了如何使用重载/调度装饰器记录 Python 函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将文档应用到多分派函数

我正在使用 multipledispatch 包,以类似于下面的示例代码的方式.当我在 Python 命令行中请求 help(my_add) 时,我希望能够看到 docstring 文本,但我看到的只是有关装饰器的信息.

Functools.wraps 必须是这样做的方式,但如何?

我查过functools.wraps,我确定这是我想要使用的.我找到了如何使用它的示例,例如 this这个.

但我仍然不完全理解两个问题:

  1. 如何将 functools.wraps 应用于我不拥有"的外部装饰器.
  2. 如何将它专门应用于这种具有多个分派的情况,因为我要包装的函数将具有多个与相同函数名称相关联的 docstrings.

示例:装饰函数创建

下面是一个帮助解释的例子.

<预><代码>>>>从多分派进口分派>>>@dispatch(str, str)... def my_add(elem1, elem2):... '''一种'add'的味道,其中两个字符串连接在一起.'''...返回 elem1 + ' ' + elem2...>>>@dispatch(int, int)... def my_add(elem1, elem2):... ''''my_add' 的一种风格,其中两个字符串连接在一起.'''...返回 elem1 + elem2...>>>my_add('嘿','你')'嘿,你'>>>my_add(4, 5)9>>>my_add(4.5, 6)

(已删除追溯详细信息...)

KeyError: (, )在处理上述异常的过程中,又发生了一个异常:NotImplementedError: 找不到 my_add 的签名:<float, int>

我想显示该错误和不同的调度,只是为了表明该部分按我的意愿工作(寻找匹配的调度并调用函数的相关风味").

示例:在装饰函数上调用help 失败!

但是接下来,如果我尝试查看帮助,我会看到与 @dispatch 装饰器关联的文档字符串,而不是我提供的简单 docstring.

<预><代码>>>>帮助(my_add)模块 multipledispatch.dispatcher 对象中的 Dispatcher 帮助:my_add = class Dispatcher(builtins.object)|此处定义的方法:||__call__(self, *args, **kwargs)|将 self 作为函数调用.||__getstate__(自我)|

<小时>

我什至不确定它应该显示什么,因为有可能有 2 个冲突的文档字符串我想继续推进.因此,我尝试查看是否可以对实际运行的函数调用帮助,但当然它会为我提供有关返回数据类型的帮助.例如,

<预><代码>>>>帮助(my_add(3, 5))关于 int 对象的帮助:类 int(对象)|int(x=0) ->整数|int(x, base=10) ->整数||将数字或字符串转换为整数,如果没有参数则返回 0

解决方案

functools.wraps() 装饰器必须是 装饰器实现 的一部分,您可以不要事后应用它.这里的问题是装饰器返回一个自定义类的实例,而 help() 只能显示该实例的 class 的文档.

装饰器返回的 Dispatcher() 实例已经有一个 __doc__ 属性,它列出了所有装饰函数的文档字符串.从您链接的文档中:

<块引用>

Dispatcher 自动创建详细的文档字符串.要添加多方法本身的描述,请在创建 Dispatcher 时提供.

文档字符串也适用于您的示例:

<预><代码>>>>打印(my_add.__doc__)乘法调度方法:my_add输入:<str, str>-------------------'add' 的味道,其中两个字符串连接在一起.输入:<int, int>-------------------连接两个字符串的my_add"风格.

(请注意,文档字符串从您的示例中正确反映,并带有错误).

这里真正的问题是help()只能打印class__doc__字符串,所以print(type(my_add).__doc__)) 用作起点.这不是可以轻易改变的;只需坚持直接打印实例的 __doc__ 属性即可.

Applying Documentation to Multi-Dispatched Functions

I am using the multipledispatch package, in a fashion similar to the example code below. I want to be able to see the docstring text when I ask for help(my_add) in the Python command line, but instead all I see is information about the decorator.

Functools.wraps must be the way to do it, but how?

I have looked up functools.wraps, which I'm sure is what I want to use. I have found examples of how to use it, such as this and this.

But I still don't entirely understand two issues:

  1. How to apply the functools.wraps to external decorators that I don't "own".
  2. How to apply it specifically to this case with multiple dispatch, since the function I want to wrap will have multiple docstrings associated with the same function name.

Example: Decorated Function Creation

Below is an example to help explain.

>>> from multipledispatch import dispatch
>>> @dispatch(str, str)
... def my_add(elem1, elem2):
...   '''A flavor of 'add' where two strings are concatenated.'''
...   return elem1 + ' ' + elem2
... 
>>> @dispatch(int, int)
... def my_add(elem1, elem2):
...   '''A flavor of 'my_add' where two strings are concatenated.'''
...   return elem1 + elem2
... 
>>> my_add('hey','you')
'hey you'
>>> my_add(4, 5)
9
>>> my_add(4.5, 6)

(Traceback details removed...)

KeyError: (<class 'float'>, <class 'int'>)
During handling of the above exception, another exception occurred:
NotImplementedError: Could not find signature for my_add: <float, int>

I wanted to show that error and the different dispatches just to show that that part is working as I want it (looking for the matched dispatch and calling the associated "flavor" of the function).

Example: Calling help on the Decorated Function Fails!

But next, if I try to look at the help, instead of seeing the simple docstring that I have provided, I see the docstring associated with the @dispatch decorator.

>>> help(my_add)

Help on Dispatcher in module multipledispatch.dispatcher object:

my_add = class Dispatcher(builtins.object)
 |  Methods defined here:
 |  
 |  __call__(self, *args, **kwargs)
 |      Call self as a function.
 |  
 |  __getstate__(self)
 |  

etc.


I'm not even sure what it should show, since there are potentially 2 conflicting docstrings I'd like to push forward. So, I tried to see if I could call help on a function that's actually run, but then of course it gives me help on the returned data type. E.g.,

>>> help(my_add(3, 5))

Help on int object:

class int(object)
 |  int(x=0) -> integer
 |  int(x, base=10) -> integer
 |  
 |  Convert a number or string to an integer, or return 0 if no arguments

解决方案

The functools.wraps() decorator would have to be part of the decorator implementation and you can't apply it after the fact. The issue here is that the decorator returns an instance of a custom class, and help() can only show documentation for the class of that instance.

The Dispatcher() instance the decorator returns already has a __doc__ attribute, one which lists the doc strings of all decorated functions. From the documentation you linked:

The Dispatcher creates a detailed docstring automatically. To add a description of the multimethod itself, provide it when creating the Dispatcher.

The docstring is there for your example too:

>>> print(my_add.__doc__)
Multiply dispatched method: my_add

Inputs: <str, str>
-------------------
A flavor of 'add' where two strings are concatenated.

Inputs: <int, int>
-------------------
A flavor of 'my_add' where two strings are concatenated.

(note that the docstrings are reflected correctly from your example, complete with errors).

The real issue here is that help() can only print the __doc__ string of the class, so print(type(my_add).__doc__)) is used as a starting point. This is not something that can easily be changed; just stick to printing the __doc__ attribute of the instance directly.

这篇关于如何使用重载/调度装饰器记录 Python 函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆