Pergunta

Estou escrevendo extensões C, e eu gostaria de fazer a assinatura dos meus métodos visível para a introspecção.

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

Agora, se (depois de construí-la ...) eu carregar o módulo e olhar para a sua ajuda:

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

Vou começar:

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.

Gostaria de ser ainda mais específico e ser capaz de substituir foo (...) por foo (timeout, bandeiras = None)

Posso fazer isso? Como?

Foi útil?

Solução

A minha abordagem usual para descobrir sobre coisas como esta é: "usar a fonte"

Basicamente, eu presumiria que os módulos padrão de python usaria esse recurso quando disponível. Olhando para a fonte ( por exemplo aqui ) deve ajudar, mas na verdade até mesmo os módulos padrão adicionar o protótipo após a saída automática. Como esta:

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

Assim como a montante não está usando esse recurso um, eu diria que ele não está lá. : -)

Ok, eu verifiquei apenas fontes python3k atuais e esse ainda é o caso. Essa assinatura é gerada em pydoc.py nas fontes python aqui: pydoc.py . trecho relevante a partir de linha de 1260:

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

cheques inspect.isfunction se o objeto a documentação é solicitada para é uma função Python. Mas C implementado funções são consideradas builtins, portanto, você sempre terá name(...) como a saída.

Outras dicas

Tem sido 7 anos , mas você pode incluir a assinatura para a função C-extensão e aulas .

próprio Python usa o Argumento Clinic para gerar dinamicamente assinaturas. Em seguida, alguns mecânicos criar um __text_signature__ e isso pode ser introspectadas (por exemplo, com help). @MartijnPieters explicou este processo muito bem em esta resposta .

Você pode realmente começar a clínica argumento do python e fazê-lo de uma forma dinâmica, mas eu prefiro a maneira manual: Adicionando a assinatura para a docstring:

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

Eu fiz uso pesado deste no meu pacote: iteration_utilities/src . Então, para demonstrar que funciona eu usar uma das funções C-extensão expostos por este pacote:

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

O docstring para esta função é definida esse arquivo .

É importante perceber que este não é possível para python <3.4 e você precisa seguir algumas regras:

  • Você precisa incluir --\n\n após a linha de definição de assinatura.

  • A assinatura deve estar na primeira linha da docstring.

  • A assinatura deve ser válido, ou seja, foo(a, b=1, c) falhar porque não é possível definir argumentos posicionais após discussões com padrão.

  • Você só pode fornecer uma assinatura. Então, ele não funciona se você usar algo como:

    foo(a)
    foo(x, a, b)
    --
    
    Narrative documentation
    
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top