PEP 257 em russo. (Docstrings Agreement)

Olá, Habr. Há momentos em que você deseja mergulhar na língua o máximo possível e entender todas as sutilezas. No caso do Python, uma das melhores maneiras de fazer isso é ler a documentação e as PEPs no site oficial. Eu não fiz isso na época, porque não conseguia entender muitos dos aspectos "técnicos" e não havia variantes da tradução para o russo. Agora eu decidi traduzir o PEP-257, o que explica a documentação correta do código, porque com certeza isso ajudará os iniciantes a entender melhor a verdadeira abordagem "Python" para escrever código. Traduzi os exemplos de código para o russo, mas apenas para transmitir melhor o significado. Na programação real, tente escrever linhas de documentação em inglês. Também digo imediatamente que, como sinônimo do termo "docstring", usei as palavras "documentação" e "linhas de documentação". Bem, vamos à tradução em si.

Pep257
Título:Docstrings Agreement
Autores:David Goodger <goodger em python.org>, Guido van Rossum <guido em python.org>
Discussão:doc-sig em python.org
Estado:Ativo
Um tipo:Informativo
Criada:29 de maio de 2001
Publicação:13 de junho de 2001

anotação


Este PEP documenta a semântica e as convenções associadas ao uso de documentos em Python.

Justificação


O objetivo deste PEP é padronizar a estrutura de alto nível das linhas de documentos: descrever exatamente o que elas devem conter e explicar (não discutiremos a sintaxe de marcação real). O PEP não contém diretrizes rígidas, mas recomendações:
“As convenções convencionais oferecem clareza, consistência, facilidade de manutenção e promovem bons hábitos de programação. Mas eles não o forçam a agir contra sua vontade. Este é o Python!

Tim Peters em comp.lang.python, 16/06/2001

Se você evitar acordos geralmente aceitos, será estressado na pior das hipóteses. Porém, existem alguns aplicativos (por exemplo, sistemas de documentação como o Docutils) que permitem obter um resultado melhor se você conhecer os acordos e segui-los.

Especificação


O que é uma Docstring?


Uma string de documentação é uma literal de string que é a primeira instrução em uma definição de módulo, função, classe ou método. Essa string fica disponível ao manipular o atributo __doc__ especial desse objeto.

Todas as bibliotecas, assim como as funções e classes exportadas por elas, devem ter uma cadeia de caracteres. Métodos públicos (incluindo o construtor __ init__) também devem ter documentação. O pacote em si pode ser documentado dentro do arquivo __init__.py localizado em seu diretório correspondente.

Literais de string encontrados em outras partes do código também podem desempenhar o papel de documentação. Eles não são reconhecidos pelo compilador de código de bytes do Python e não estão disponíveis como atributos de objeto durante a execução do programa (ou seja, eles não possuem informações em __ doc__). Mas existem dois tipos adicionais de linhas de documentação que são recuperadas usando outras ferramentas de software:

  1. Literais de string que ocorrem imediatamente após uma atribuição simples no módulo, classe ou nível __init__ são chamados de "strings de documentação de atributos". (atributo docstrings)
  2. Literais de seqüência de caracteres que ocorrem imediatamente após outra linha de documentação são chamados de "linhas de documentação adicionais". (documentos adicionais)

Consulte o PEP 258, “Especificação do projeto Docutils”, para obter mais detalhes sobre atributos e documentos adicionais.

[Aproximadamente. ed. Explicação da PEP 258]
def f(x):
    """  docstring   __doc__ ."""
    """
     "additional docstrings",   , 
        Docutils.
    """
    return x**2

f.a = 1
""" "attribute docstrings"   : f.a"""

Para obter consistência, sempre use "" "aspas duplas triplas" "" na linha de documentação. Se você usar caracteres de barra invertida ("\"), use a r "" "sequência bruta de aspas duplas" "" na sua documentação. Para docstring contendo caracteres Unicode, use u "" "String Unicode entre aspas duplas triplas" "". [Aproximadamente. cadeias unicode perderam o significado no python 3.x]

Existem duas formas de cadeia de caracteres: linha única e multilinha.

Linhas de documentação de linha única


Sequências de linha única são usadas para casos óbvios e devem realmente estar na mesma linha. Por exemplo:

def kos_root():
    """    root KOS"""
    global _kos_root
    if _kos_root: return _kos_root
    ...

Observações:

  • . .
  • , . docstring .
  • , .
  • — «», . (« », « »), . , : « ...».

    « » «Return pathname» «Returns pathname». PEP-257 , .
  • «», / ( ). :

    def function(a, b):
        """function(a, b) -> list"""
    

    , C ( ), . . - :

    def function(a, b):
        def function(a, b):
        """ X   ."""
    

    ( -, « X» !)

    , : « », «description» . , , .



A documentação de várias linhas consiste em uma linha de resumo que possui a mesma estrutura que uma cadeia de caracteres de linha única, seguida por uma linha vazia e, em seguida, uma descrição mais complexa. "Linha de resumo" pode ser usada por meio de documentação automática; portanto, é tão importante colocá-lo em uma linha e depois passar em uma linha. A linha de resumo é escrita imediatamente após as aspas de abertura, mas é permitido fazer uma hifenização e começar a partir da próxima linha. [Aproximadamente. depois dessa frase, fiquei feliz, porque havia pessoas que tentaram persistentemente me provar que era impossível realizar uma transferência em qualquer caso :-)] Ao mesmo tempo, toda a doutrina deve ter o mesmo recuo que as aspas iniciais da primeira linha (veja o exemplo abaixo).

Deixe uma linha em branco após toda a documentação (linha única ou multilinha) usada na classe; de um modo geral, os métodos de classe devem ser separados um do outro por uma linha vazia; portanto, a linha de documentação da classe também deve ser separada dessa maneira do primeiro método.

A documentação do script (programa independente) é uma mensagem "sobre uso adequado" e provavelmente será impressa quando o script for chamado com argumentos inválidos ou ausentes (ou com a opção "-h" para obter "ajuda"). Essa linha de documentação deve descrever a funcionalidade e a sintaxe dos parâmetros do script, bem como variáveis ​​e arquivos de ambiente usados. Essa mensagem pode ser bastante complicada (o manual tem várias telas inteiras), mas ao mesmo tempo deve ser conveniente para novos usuários, para que possam usar o comando corretamente. Além disso, o manual deve fornecer uma descrição clara de todos os parâmetros e argumentos para usuários mais experientes.

A documentação do módulo geralmente deve conter uma lista de classes, exceções e funções (e quaisquer outros objetos importantes) exportados usando a biblioteca, além de uma explicação de uma linha para cada uma delas. (Este resumo, em regra, fornece menos detalhes do que a linha de resumo na documentação do próprio objeto). A documentação do pacote (ou seja, a documentação do módulo em __init__.py) também deve descrever e listar os módulos e subpacotes exportados pelo principal.

A documentação de uma função ou método deve descrever seu comportamento, argumentos, valores de retorno, efeitos colaterais, exceções e restrições sobre quando eles podem ser chamados (se houver). Você também deve especificar argumentos opcionais. Deve ser esclarecido se os principais argumentos fazem parte da interface.

A documentação da classe deve resumir seu comportamento e listar métodos públicos, bem como variáveis ​​de instância. Se a classe tiver subclasses com uma interface adicional, essa interface deverá ser especificada separadamente (mas tudo também está nesta documentação). O construtor da classe deve ter sua própria linha de documentação separada para o método __init__. Métodos independentes (individuais) devem ter sua própria documentação.

Se uma classe é descendente e seu comportamento é principalmente herdado da classe principal, é necessário mencionar isso em sua documentação e descrever possíveis diferenças. Use o verbo "substituir" para indicar que um método foi alterado e que, como resultado, o método da superclasse não será chamado. Use o verbo "extends" se o método da subclasse chamar o método da superclasse (além de seu próprio comportamento).

Não use a convenção do Emacs para mencionar argumentos ou métodos de função em maiúsculas. O Python faz distinção entre maiúsculas e minúsculas e, às vezes, os nomes dos argumentos podem ser usados ​​ao passar por chaves, portanto a documentação deve conter nomes reais de variáveis. É melhor listar cada argumento em uma linha separada. Por exemplo:

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

     :
    real --   (  0.0)
    imag --   (  0.0)
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    ...


Se a sequência de caracteres inteira não couber na linha, você pode colocar as aspas de fechamento em uma linha separada. Assim, será possível usar o comando Emacs: fill-paragraph

Processamento de Docstring


As ferramentas de processamento de linha de documentação devem remover o mesmo número de recuo igual ao recuo mínimo de todas as linhas não vazias, começando pela segunda. Qualquer indentação na primeira linha da documentação não é significativa e será excluída. O recuo relativo das linhas posteriores na linha do documento é mantido. Linhas vazias devem ser removidas do início e do fim da linha do documento.

Como o código é muito mais preciso que as palavras, aqui está a implementação do algoritmo:

def trim(docstring):
    if not docstring:
        return ''
    #     (  Python)
    #      :
    lines = docstring.expandtabs().splitlines()
    #    (   ):
    indent = sys.maxsize
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    #   (   ):
    trimmed = [lines[0].strip()]
    if indent < sys.maxsize:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    #       :
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    #    :
    return '\n'.join(trimmed)

Nota do tradutor
, python3 sys.maxint sys.maxsize, .


A documentação no exemplo a seguir contém duas novas linhas e, portanto, possui um comprimento de três. A primeira e a última linha estão vazias:

def foo ():
    """
       .
    """

Ilustramos:

>>> print repr(foo.__doc__)
'\n        .\n    '
>>> foo.__doc__.splitlines()
['', '        .', '    ']
>>> trim(foo.__doc__)
'    .'

Assim, após o processamento, as seguintes linhas de documentação serão equivalentes:

def foo():
    """ 
     .
    """

def bar():
    """
     
     .
    """

Nota do tradutor
inspect, , : inspect.cleandoc(function.__doc__)


All Articles