Pregunta

Estoy escribiendo extensiones C, y me gustaría hacer la firma de mis métodos visibles para la introspección.

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");
}

Ahora bien, si (después de su construcción ...) me carga el módulo y miro su ayuda:

>>> import _myexample
>>> help(_myexample)

voy a tener:

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.

Me gustaría ser aún más específico y ser capaz de sustituir foo (...) por foo (tiempo de espera, banderas = None)

¿Puedo hacer esto? ¿Cómo?

¿Fue útil?

Solución

Mi enfoque habitual para enterarse de cosas como esta es: "usar la fuente"

.

Básicamente, lo que supondría que los módulos estándar de Python usarían esta característica cuando esté disponible. En cuanto a la fuente ( por ejemplo, aquí ) debería ayudar, pero, de hecho, incluso los módulos estándar añadir el prototipo después de la salida automática. De esta manera:

torsten@pulsar:~$ python2.6
>>> import fcntl
>>> help(fcntl.flock)
flock(...)
    flock(fd, operation)

    Perform the lock operation op on file descriptor fd.  See the Unix [...]

Así como aguas arriba no está utilizando esta característica, quiero suponer que no está allí. : -)

Bueno, acabo de comprobar las fuentes python3k actuales y esto es todavía el caso. Que la firma se genera en pydoc.py en las fuentes de pitón aquí: pydoc.py . de partida extracto relevante en la línea 1260:

        if inspect.isfunction(object):
            args, varargs, varkw, defaults = inspect.getargspec(object)
            ...
        else:
            argspec = '(...)'

cheques inspect.isfunction si el objeto se solicita la documentación de es una función Python. Pero C implementa funciones se consideran órdenes internas, por lo tanto, siempre obtendrá name(...) como la salida.

Otros consejos

Ha sido 7 años pero se puede incluir la firma de función C-extensión y clases .

sí Python utiliza el Argumento Clinic para generar dinámicamente firmas. Entonces algunos mecánicos crean una __text_signature__ y esto se puede introspección (por ejemplo, con help). @MartijnPieters explican este proceso bastante bien en esta respuesta .

Usted puede conseguir realmente el centro de discusión de Python y hacerlo de una manera dinámica, pero yo prefiero la forma manual: Adición de la firma a la cadena de documentación:

En su caso:

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.");

he hecho un uso intensivo de esto en mi paquete: iteration_utilities/src . Así que para demostrar que funciona utilizo una de las funciones de extensión C-expuestos por este paquete:

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

El docstring para esta función se define este archivo .

Es importante darse cuenta de que este no es posible para el pitón <3,4 y es necesario seguir algunas reglas:

  • Es necesario incluir --\n\n después de la línea de la firma definición.

  • La firma debe estar en la primera línea de la cadena de documentación.

  • La firma debe ser válido, es decir foo(a, b=1, c) falla porque no es posible definir los argumentos posicionales después de discusiones con defecto.

  • Sólo puede proporcionar una firma. Por lo tanto, no funciona si se utiliza algo como:

    foo(a)
    foo(x, a, b)
    --
    
    Narrative documentation
    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top