1

次のように、Python 関数のファーストクラスの性質を利用して定義された関数があります。

add_relative = np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)

定義された関数に docstring をそのまま追加する方法が必要です。または、通常の方法で docstring を記述できるように、より一般的な形式を使用して同じことを実現する必要があります。

def add_relative(a, b):
    """
    Docstring
    """
    return np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)(a, b)

関数が次のように呼び出されたときに機能します

 add_relative(arr1, arr2)

しかし、その後、メソッドを呼び出すことができなくなります。たとえば、

add_relative.accumulate(foo_arr, dtype=np.object)

frompyfuncこれは、 から派生した を使用すると、関数がよりクラスのようになるためだと思いufuncます。

関数ではなくクラスを定義する必要があるかもしれないと考えていますが、方法がわかりません。通常どおり docstring を簡単に追加できるので、それで問題ありません。

元の方法は機能しますが、簡単に文書化できないため、これにタグを付けましcoding-styleた。タイトルが明確でない場合は申し訳ありませんが、これを説明する正しい語彙がわかりません。

4

2 に答える 2

2

更新 1: 終了しますが、これではまだ十分ではありません。装飾された関数の__doc__属性は更新できず、Sphinx はまだ装飾された関数の docstring しか取得しないため、これで問題は解決しません。

更新 2: 以下で提案するソリューションは、ソース コード内のドキュメントに適しています。Sphinx のドキュメントについては、ドキュメント文字列を次のように上書きするだけで済みました。

.. function:: sum_relative(a, b)

   <Docstring written in rst format>

醜く、ハックで、手動ですが、ソース コードに優れたドキュメントがあり、Sphinx に優れたドキュメントがあることを意味します。

All of the issues stem from the fact that the __doc__ attribute of a numpy.ufunc is immutable. If anyone knows why, I'd love to hear why. I'm guessing something related to the fact that it comes from something written in C, not pure Python. Regardless, it's very annoying.


I found that I could solve the issue using a decorator to apply np.frompyfunc().

I write the base function (the lambda in the original example) and add a docstring as normal and then apply the decorator:

def as_ufunc(func):
    return np.frompyfunc(func, 2, 1)

@as_ufunc
def sum_relative(a, b):
    """
    Docstring
    """
    return (1 + a) * (1 + b) - 1

It's not a perfect solution for the following reasons:

  • sum_relative.__doc__ is overwritten by frompyfunc to a generic and unhelpful docstring. I don't mind here because I really care about the docs generated with Sphinx from the docstring, and not accessing it programatically. You might think to try something like functools.wraps or functools.update_wrapper, however the __doc__ member of a numpy.ufunc is apparenly immutable.

  • I have to hardcode the second two arguments for frompyfunc. I don't mind here because all the cases that I use it here will require the same values.

  • Edit: It is possible to get around the above point, it's a little more verbose, but not much:

    def as_ufunc(nin, nout):
        def _decorator(func):
            return np.frompyfunc(func, nin, nout)
        return _decorator
    
    @as_ufunc(2, 1)
    def sum_relative(a, b):
        """
        Docstring
        """
        return (1 + a) * (1 + b) - 1
    
  • It's more verbose than the original solution. I don't mind because I now have the docstring.
于 2016-12-20T15:22:33.673 に答える