如何使用重载/调度装饰器来记录Python函数?

时间:2018-01-19 18:42:55

标签: python operator-overloading python-decorators dispatch

将文档应用于多分派函数

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

Functools.wraps必须是这样做的,但是怎么做?

我查了functools.wraps,我确信这就是我想要使用的内容。我找到了如何使用它的示例,例如thisthis

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

  1. 如何将functools.wraps应用于我不会"拥有"。
  2. 的外部装饰者
  3. 如何通过多次调度专门应用于此案例,因为我要包装的函数将有多个docstrings与相同的函数名相关联。
  4. 示例:装饰函数创建

    以下是帮助解释的示例。

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

    (删除了回溯详​​情......)

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

    我想显示错误和不同的调度只是为了表明该部分正在按我的意愿工作(寻找匹配的调度并调用相关的&#34; flavor&#34;该函数)。

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

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

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

    我甚至不确定应该显示什么,因为 可能存在2个冲突的文档字符串 我喜欢推进。所以,我试着看看我是否可以在实际运行的函数上调用帮助,但当然它给了我关于返回数据类型的帮助。如,

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

1 个答案:

答案 0 :(得分:1)

functools.wraps()装饰器必须是装饰器实现的一部分,并且您无法在事后应用它。这里的问题是装饰器返回自定义类的实例,而help()只能显示该实例的的文档。

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

  

Dispatcher会自动创建详细的文档字符串。要添加多方法本身的说明,请在创建Dispatcher时提供。

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

>>> 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.

(请注意,文档字符串会从您的示例中正确反映出来,并且会出现错误)。

这里的真正问题是help()只能打印__doc__字符串,因此print(type(my_add).__doc__))用作起点。这不是一件容易改变的事情;只是坚持直接打印实例的__doc__属性。