我正在编写 C 扩展,并且我想让我的方法的签名可见以便自省(introspection)。
static PyObject* foo(PyObject *self, PyObject *args) {
/* blabla [...] */
}
PyDoc_STRVAR(
foo_doc,
"Great example function\n"
"Arguments: (timeout, flags=None)\n"
"Doc blahblah doc doc doc.");
static PyMethodDef methods[] = {
{"foo", foo, METH_VARARGS, foo_doc},
{NULL},
};
PyMODINIT_FUNC init_myexample(void) {
(void) Py_InitModule3("_myexample", methods, "a simple example module");
}
现在如果(在构建它之后......)我加载模块并查看它的帮助:
>>> import _myexample
>>> help(_myexample)
我会得到:
Help on module _myexample:
NAME
_myexample - a simple example module
FILE
/path/to/module/_myexample.so
FUNCTIONS
foo(...)
Great example function
Arguments: (timeout, flags=None)
Doc blahblah doc doc doc.
我想更具体一点,能够用 foo(timeout, flags=None) 替换 foo(...)
我可以这样做吗?怎么办?
最佳答案
已经 7 年了但您可以包含 C 扩展函数和类的签名。
Python 本身使用 Argument Clinic动态生成签名。然后一些机制创建了一个 __text_signature__
并且可以对其进行自省(introspection)(例如使用 help
)。 @MartijnPieters 在 this answer 中很好地解释了这个过程.
您实际上可以从 python 获取参数 clinic 并以动态方式进行,但我更喜欢手动方式:将签名添加到文档字符串:
在你的情况下:
PyDoc_STRVAR(
foo_doc,
"foo(timeout, flags=None, /)\n"
"--\n"
"\n"
"Great example function\n"
"Arguments: (timeout, flags=None)\n"
"Doc blahblah doc doc doc.");
我在我的包中大量使用了这个:iteration_utilities/src
.因此,为了证明它的工作原理,我使用了此包公开的 C 扩展函数之一:
>>> from iteration_utilities import minmax
>>> help(minmax)
Help on built-in function minmax in module iteration_utilities._cfuncs:
minmax(iterable, /, key, default)
Computes the minimum and maximum values in one-pass using only
``1.5*len(iterable)`` comparisons. Recipe based on the snippet
of Raymond Hettinger ([0]_) but significantly modified.
Parameters
----------
iterable : iterable
The `iterable` for which to calculate the minimum and maximum.
[...]
此函数的文档字符串已定义 this file .
重要的是要意识到这对于 python < 3.4 是不可能的,您需要遵循一些规则:
您需要在签名定义行之后包含
--\n\n
。签名必须在文档字符串的第一行。
签名必须有效,即
<foo(a, b=1, c)
失败,因为无法在默认参数之后定义位置参数。您只能提供一个签名。因此,如果您使用类似的东西,它就不起作用:
foo(a) foo(x, a, b) -- Narrative documentation
关于Python C 扩展 : method signatures for documentation?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1104823/