Como documentar um método com parâmetro (s)?

139

Como documentar métodos com parâmetros usando as strings de documentação do Python?

EDIT: PEP 257 dá este exemplo:

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Essa é a convenção usada pela maioria dos desenvolvedores de Python?

Keyword arguments:
<parameter name> -- Definition (default value if any)

Eu esperava algo um pouco mais formal, como

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    @param: real The real part (default 0.0)
    @param: imag The imaginary part (default 0.0)

    """
    if imag == 0.0 and real == 0.0: return complex_zero
    ...

Ambiente : Python 2.7.1

David Andreoletti
fonte
1
Você leu PEP 257? python.org/dev/peps/pep-0257
NPE
1
Existem vários 'padrões' por aí, mas em uma abordagem prática e, especialmente, se você gosta de algo formal, eu recomendaria a esfinge . Sua integração no Pycharm torna a geração de documentos bem estruturados um tanto indolor. IMHO
jojo

Respostas:

86

Com base na minha experiência, as convenções numpy docstring (superconjunto PEP257) são as convenções seguidas mais amplamente difundidas e também suportadas por ferramentas, como o Sphinx .

Um exemplo:

Parameters
----------
x : type
    Description of parameter `x`.
Vladimir Keleshev
fonte
2
Isso está mais perto do que eu esperava. Infelizmente, escolhi o PEP 257 simples e adicionei minha própria convenção (com o custo de perder a documentação HTML / PDF gerada automaticamente). No entanto, da próxima vez, vou escolher esta solução. Obrigado.
David Andreoletti
5
Quando tento processar sua documentação sugerida, o Sphinx reclama SEVERE: Unexpected section title- você conhece alguma maneira de tornar o Sphinx mais feliz com isso?
Brandon Rhodes
@BrandonRhodes este link fala sobre o uso dessas convenções com o Sphinx: github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
Vladimir Keleshev
3
Na verdade, falta um espaço antes Description. Verifiquei a documentação numpy, porque imediatamente notei e pensei "Espere um segundo, por que são três espaços? Isso é estranho. Quem usaria três espaços?"
Zelphir Kaltstahl
6
Esta pode ter sido a melhor resposta no momento em que a pergunta foi feita, mas acho que a partir de agora (final de 2017), a Sphinx saiu vitoriosa.
Alex L
120

Como as docstrings são de formato livre, isso realmente depende do que você usa para analisar o código e gerar a documentação da API.

Eu recomendaria se familiarizar com a marcação Sphinx , pois é amplamente usada e está se tornando o padrão de fato para documentar projetos Python, em parte devido ao excelente serviço readthedocs.org . Para parafrasear um exemplo da documentação Esfinge como um trecho Python:

def send_message(sender, recipient, message_body, priority=1):
   '''
   Send a message to a recipient

   :param str sender: The person sending the message
   :param str recipient: The recipient of the message
   :param str message_body: The body of the message
   :param priority: The priority of the message, can be a number 1-5
   :type priority: integer or None
   :return: the message id
   :rtype: int
   :raises ValueError: if the message_body exceeds 160 characters
   :raises TypeError: if the message_body is not a basestring
   '''

Essa marcação oferece suporte à referência cruzada entre documentos e muito mais. Observe que a documentação do Sphinx usa (por exemplo), :py:attr:enquanto você pode apenas usar :attr:ao documentar a partir do código-fonte.

Naturalmente, existem outras ferramentas para documentar APIs. Existe o Doxygen mais clássico, que usa \param comandos, mas esses não foram projetados especificamente para documentar o código Python como o Sphinx.

Observe que há uma pergunta semelhante com uma resposta semelhante aqui ...

anarcat
fonte
9
Este é o estilo usado por comentário autogeneration de PyCharm por padrão
Josias Yoder
E a sintaxe dos tipos compostos, como listas de itens?
matanster
então é um list.
Anarcat 01/07
33

Convenções:

Ferramentas:


Atualização: Desde o Python 3.5, você pode usar dicas de tipo, uma sintaxe compacta e legível por máquina:

from typing import Dict, Union

def foo(i: int, d: Dict[str, Union[str, int]]) -> int:
    """
    Explanation: this function takes two arguments: `i` and `d`.
    `i` is annotated simply as `int`. `d` is a dictionary with `str` keys
    and values that can be either `str` or `int`.

    The return type is `int`.

    """

A principal vantagem dessa sintaxe é que ela é definida pelo idioma e não é ambígua, de modo que ferramentas como o PyCharm podem facilmente tirar vantagem disso.

Jakub Roztocil
fonte
12
Embora essa resposta agora seja a mais votada, nenhum dos PEPs acima fornece uma convenção para especificar os tipos de argumentos de um método.
precisa saber é
11

As strings de documentos python são de formato livre , você pode documentá-lo da maneira que desejar.

Exemplos:

def mymethod(self, foo, bars):
    """
    Does neat stuff!
    Parameters:
      foo - a foo of type FooType to bar with.
      bars - The list of bars
    """

Agora, existem algumas convenções, mas o python não aplica nenhuma delas. Alguns projetos têm suas próprias convenções. Algumas ferramentas para trabalhar com documentos também seguem convenções específicas.

nosklo
fonte
3

O mainstream é, como outras respostas aqui já apontaram, provavelmente seguindo o caminho da Esfinge para que você possa usar o Sphinx para gerar esses documentos sofisticados posteriormente.

Dito isto, eu pessoalmente uso ocasionalmente o estilo de comentários embutidos.

def complex(  # Form a complex number
        real=0.0,  # the real part (default 0.0)
        imag=0.0  # the imaginary part (default 0.0)
        ):  # Returns a complex number.
    """Form a complex number.

    I may still use the mainstream docstring notation,
    if I foresee a need to use some other tools
    to generate an HTML online doc later
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    other_code()

Mais um exemplo aqui, com alguns pequenos detalhes documentados em linha:

def foo(  # Note that how I use the parenthesis rather than backslash "\"
          # to natually break the function definition into multiple lines.
        a_very_long_parameter_name,
            # The "inline" text does not really have to be at same line,
            # when your parameter name is very long.
            # Besides, you can use this way to have multiple lines doc too.
            # The one extra level indentation here natually matches the
            # original Python indentation style.
            #
            # This parameter represents blah blah
            # blah blah
            # blah blah
        param_b,  # Some description about parameter B.
            # Some more description about parameter B.
            # As you probably noticed, the vertical alignment of pound sign
            # is less a concern IMHO, as long as your docs are intuitively
            # readable.
        last_param,  # As a side note, you can use an optional comma for
                     # your last parameter, as you can do in multi-line list
                     # or dict declaration.
        ):  # So this ending parenthesis occupying its own line provides a
            # perfect chance to use inline doc to document the return value,
            # despite of its unhappy face appearance. :)
    pass

Os benefícios (como @ mark-horvath já apontou em outro comentário) são:

  • Mais importante, os parâmetros e seus documentos sempre ficam juntos, o que traz os seguintes benefícios:
  • Menos digitação (não é necessário repetir o nome da variável)
  • Manutenção mais fácil ao alterar / remover variável. Nunca haverá um parágrafo de documento de parâmetro órfão depois que você renomear algum parâmetro.
  • e mais fácil encontrar comentários ausentes.

Agora, alguns podem pensar que esse estilo parece "feio". Mas eu diria que "feio" é uma palavra subjetiva. Uma maneira mais neutra é dizer, esse estilo não é popular, portanto pode parecer menos familiar para você e, portanto, menos confortável. Novamente, "confortável" também é uma palavra subjetiva. Mas o ponto é que todos os benefícios descritos acima são objetivos. Você não pode alcançá-los se seguir o caminho padrão.

Esperançosamente, algum dia no futuro, haverá uma ferramenta geradora de documentos que também poderá consumir esse estilo embutido. Isso conduzirá a adoção.

PS: Essa resposta deriva da minha preferência de usar comentários embutidos sempre que achar necessário. Também uso o mesmo estilo embutido para documentar um dicionário .

RayLuo
fonte
1

Com base na resposta de dicas de tipo ( https://stackoverflow.com/a/9195565/2418922 ), que fornece uma maneira melhor estruturada de documentar tipos de parâmetros, também existe uma maneira estruturada de documentar tipos e descrições de parâmetros:

def copy_net(
    infile: (str, 'The name of the file to send'),
    host: (str, 'The host to send the file to'),
    port: (int, 'The port to connect to')):

    pass

exemplo adotado em: https://pypi.org/project/autocommand/

DreamFlasher
fonte
1
Essa é uma sintaxe oficial? É super útil, porém não consigo encontrá-lo nos documentos oficiais / PEPs ...
Ofri Raviv
1
Eu também gostaria de saber se existe um PEP.
DreamFlasher 9/03
-1

As docstrings são úteis apenas em ambientes interativos, por exemplo, o shell Python. Ao documentar objetos que não serão usados ​​interativamente (por exemplo, objetos internos, retornos de chamada da estrutura), você também pode usar comentários regulares. Aqui está um estilo que eu uso para colocar comentários recuados em itens, cada um em sua própria linha, para que você saiba que o comentário está se aplicando a:

def Recomputate \
  (
    TheRotaryGyrator,
      # the rotary gyrator to operate on
    Computrons,
      # the computrons to perform the recomputation with
    Forthwith,
      # whether to recomputate forthwith or at one's leisure
  ) :
  # recomputates the specified rotary gyrator with
  # the desired computrons.
  ...
#end Recomputate

Você não pode fazer esse tipo de coisa com docstrings.

Lawrence D'Oliveiro
fonte
46
Oh, este parece feio.
Misha Akovantsev
1
Feio sim? Idéia interessante ... também sim.
David
2
Os comentários embutidos para as variáveis ​​são muito sensíveis, menos digitação (não é necessário repetir o nome da variável), manutenção mais fácil ao alterar / remover a variável ... mais fácil encontrar comentários ausentes. Combinaria com a documentação adequada abaixo da assinatura. +1
Mark Horvath
Isso não funciona como documentação. Se você comentar o seu pacote assim e um usuário do PyCharm fizer o download, ele não poderá verificar o que cada parâmetro faz sem acessar a documentação - o que você não poderá gerar com nenhum software. A menos que você faça o seu próprio. É por isso que o OP solicita especificá-lo na documentação. Desculpe tão tarde.
Isso é horrível.
Michael Walters