我正在编写 C 扩展,并且我想让我的方法的签名可见以供内省。
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__
并且可以对其进行内省(例如使用 help
)。 @MartijnPieters 在这个答案中很好地解释了这个过程。
您实际上可以从 python 获取参数诊所并以动态方式进行操作,但我更喜欢手动方式:将签名添加到文档字符串中:
您的情况:
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.
[...]
此函数的文档字符串已定义此文件。
重要的是要认识到这对于Python来说是不可能的< 3.4并且你需要遵循一些规则:
您需要在签名定义行之后包含
--\n\n
。签名必须位于文档字符串的第一行。
签名必须有效,即
foo(a, b=1, c)
失败,因为无法在默认参数之后定义位置参数。您只能提供一个签名。所以如果你使用类似的东西它就不起作用:
foo(a)
foo(x, a, b)
--
Narrative documentation
我查找此类问题的常用方法是:“使用来源”。
基本上,我认为 python 的标准模块会在可用时使用这样的功能。查看源代码(例如此处)应该会有所帮助,但事实上,即使标准模块也会在自动输出后添加原型。像这样:
torsten@pulsar:~$ python2.6 >>> 导入 fcntl >>> 帮助(fcntl.flock) 群(...) 羊群(FD,操作) 对文件描述符fd执行锁定操作op。请参阅 Unix [...]
由于上游没有使用这样的功能,我认为它不存在。 :-)
好吧,我刚刚检查了当前的 python3k 源代码,情况仍然如此。该签名是在 python 源代码中的
pydoc.py
中生成的:pydoc.py。从第 1260 行开始的相关摘录:
如果检查.isfunction(对象): args、varargs、varkw、默认值=inspect.getargspec(object) ... 别的: argspec = '(...)'
inspect.isfunction 检查请求文档的对象是否是 Python 函数。但 C 实现的函数被视为内置函数,因此您始终会得到
name(...)
作为输出。
如果有帮助的话,我发现类似下面的东西可以提供类型签名,并让 PyCharm 理解类型。
对于应具有以下签名的函数(并且第二个参数是可选的):
def function(paramA: str, paramB: bool = False) -> str:
我将在 PyMethodDef 的 ml_doc 字段中使用以下内容:
"function(paramA, /, paramB=False)\n--\nn"
"function(paramA: str, paramB: bool=False) -> str\n"
":param str paramA: blah blah blah\n"
":param str paramB: blah blah blah\n"
":returns: blah blah blah\n"
":rtype: str\n\n"
"some narrative description of the function"
“”之前的所有内容 -- " 由 python 用于填充方法上的
__text_signature__
。其余部分进入 __doc__
。PyCharm 解析 __doc__
以找出类型。:rtype:
行末尾的双换行符对于 PyCharm 来说是必要的正确处理,否则将附上以下说明。