记录 first-class-assigned 个函数
Documenting first-class-assigned functions
我有一个利用Python函数的first-class性质定义的函数,如下:
add_relative = np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)
要么我需要一种方法将文档字符串添加到定义的函数中,要么使用更常见的格式实现相同的目的,以便我可以以正常方式编写文档字符串:
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
时变得更像 class,是从 ufunc
.
派生的
我想我可能需要定义一个 class,而不是一个函数,但我不确定如何定义。我会同意的,因为这样我就可以像往常一样轻松添加文档字符串。
我标记了这个 coding-style
因为原来的方法有效但不容易记录下来,如果标题不清楚我很抱歉,我不知道正确的词汇来描述这个.
更新 1:
关闭,但这还不够好。因为装饰函数的 __doc__
属性无法更新,而且因为 Sphinx 仍然只提取装饰函数的文档字符串,所以这并不能解决我的问题。
更新二:
我在下面提出的解决方案非常适合源代码中的文档。对于 Sphinx 的文档,我最终只是用
覆盖了文档字符串
.. function:: sum_relative(a, b)
<Docstring written in rst format>
它很丑陋,很老套,而且是手动的,但这意味着我在源代码中有我很好的文档,我在 Sphinx 中有我很好的文档。
所有问题都源于 numpy.ufunc
的 __doc__
属性是不可变的。如果有人知道为什么,我很想听听为什么。我猜测它来自用 C 编写的东西,而不是纯粹的 Python。无论如何,这很烦人。
我发现我可以使用装饰器来解决问题 np.frompyfunc()
。
我编写基本函数(原始示例中的 lambda)并正常添加文档字符串,然后应用装饰器:
def as_ufunc(func):
return np.frompyfunc(func, 2, 1)
@as_ufunc
def sum_relative(a, b):
"""
Docstring
"""
return (1 + a) * (1 + b) - 1
由于以下原因,这不是一个完美的解决方案:
sum_relative.__doc__
被 frompyfunc
覆盖为通用且无用的文档字符串。我在这里不介意,因为我真的很关心从文档字符串中使用 Sphinx 生成的文档,而不是以编程方式访问它。您可能会想尝试 functools.wraps
或 functools.update_wrapper
,但是 numpy.ufunc
的 __doc__
成员显然是不可变的。
我必须对 frompyfunc
的后两个参数进行硬编码。我在这里不介意,因为我在这里使用它的所有情况都需要相同的值。
编辑:上面的点是可以绕过的,有点冗长,但不多:
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
- 它比原来的解决方案更冗长。我不介意,因为我现在有了文档字符串。
我认为这样的方法可能有效:
UFUNC_ATTRS = (
'nin',
'accumulate',
# etc...
)
def redirectattribtues(destination):
def decorator(func):
for attribute in UFUNC_ATTRS:
setattr(func, attribute, getattr(destination, attribute))
return func
return decorator
ufunc = np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)
@redirectattribtues(destination=ufunc)
def add_relative(a, b):
"""
Docstring
"""
return ufunc(a, b)
# test
arr1 = np.array(list(range(0, 10)))
arr2 = np.array(list(range(10, 20)))
print(add_relative(arr1, arr2))
print(add_relative.accumulate(arr1, dtype=object))
我有一个利用Python函数的first-class性质定义的函数,如下:
add_relative = np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)
要么我需要一种方法将文档字符串添加到定义的函数中,要么使用更常见的格式实现相同的目的,以便我可以以正常方式编写文档字符串:
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
时变得更像 class,是从 ufunc
.
我想我可能需要定义一个 class,而不是一个函数,但我不确定如何定义。我会同意的,因为这样我就可以像往常一样轻松添加文档字符串。
我标记了这个 coding-style
因为原来的方法有效但不容易记录下来,如果标题不清楚我很抱歉,我不知道正确的词汇来描述这个.
更新 1:
关闭,但这还不够好。因为装饰函数的 __doc__
属性无法更新,而且因为 Sphinx 仍然只提取装饰函数的文档字符串,所以这并不能解决我的问题。
更新二: 我在下面提出的解决方案非常适合源代码中的文档。对于 Sphinx 的文档,我最终只是用
覆盖了文档字符串.. function:: sum_relative(a, b)
<Docstring written in rst format>
它很丑陋,很老套,而且是手动的,但这意味着我在源代码中有我很好的文档,我在 Sphinx 中有我很好的文档。
所有问题都源于 numpy.ufunc
的 __doc__
属性是不可变的。如果有人知道为什么,我很想听听为什么。我猜测它来自用 C 编写的东西,而不是纯粹的 Python。无论如何,这很烦人。
我发现我可以使用装饰器来解决问题 np.frompyfunc()
。
我编写基本函数(原始示例中的 lambda)并正常添加文档字符串,然后应用装饰器:
def as_ufunc(func):
return np.frompyfunc(func, 2, 1)
@as_ufunc
def sum_relative(a, b):
"""
Docstring
"""
return (1 + a) * (1 + b) - 1
由于以下原因,这不是一个完美的解决方案:
sum_relative.__doc__
被frompyfunc
覆盖为通用且无用的文档字符串。我在这里不介意,因为我真的很关心从文档字符串中使用 Sphinx 生成的文档,而不是以编程方式访问它。您可能会想尝试functools.wraps
或functools.update_wrapper
,但是numpy.ufunc
的__doc__
成员显然是不可变的。我必须对
frompyfunc
的后两个参数进行硬编码。我在这里不介意,因为我在这里使用它的所有情况都需要相同的值。编辑:上面的点是可以绕过的,有点冗长,但不多:
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
- 它比原来的解决方案更冗长。我不介意,因为我现在有了文档字符串。
我认为这样的方法可能有效:
UFUNC_ATTRS = (
'nin',
'accumulate',
# etc...
)
def redirectattribtues(destination):
def decorator(func):
for attribute in UFUNC_ATTRS:
setattr(func, attribute, getattr(destination, attribute))
return func
return decorator
ufunc = np.frompyfunc(lambda a, b: (1 + a) * (1 + b) - 1, 2, 1)
@redirectattribtues(destination=ufunc)
def add_relative(a, b):
"""
Docstring
"""
return ufunc(a, b)
# test
arr1 = np.array(list(range(0, 10)))
arr2 = np.array(list(range(10, 20)))
print(add_relative(arr1, arr2))
print(add_relative.accumulate(arr1, dtype=object))