Python Docstrings
Você escreveu uma função útil. Daqui a três meses, você (ou uma colega) vai querer usá-la de novo: o que ela faz? O que é cada parâmetro? Em que unidade vai o preço? A resposta fica numa docstring (de documentation string, "texto de documentação"): um texto entre três aspas, logo abaixo do def, que explica a função. Diferente de um comentário, a docstring fica guardada dentro da função, e o Python sabe mostrá-la quando alguém pede ajuda com help().
- O que é uma docstring e onde ela fica (a primeira linha do corpo da função).
- A diferença entre docstring e comentário (
#). - A escrever docstrings de uma linha e de várias linhas, do jeito que a comunidade Python costuma escrever.
- A ler a documentação com
help()e com o atributo__doc__. - A documentar um arquivo inteiro (a docstring do módulo).
- Os erros reais: docstring fora do lugar, sem recuo e com as aspas abertas.
A ideia: a etiqueta do pote
Na cozinha da Ana, os potes de tempero são todos iguais. Sem etiqueta, ela precisa abrir, cheirar e provar para saber o que é cada um. Com uma etiqueta colada no pote ("Páprica defumada. Usar pouco: é forte."), qualquer pessoa da casa sabe o que tem dentro sem abrir.
A docstring é a etiqueta da função. Quem vai usar a função não precisa ler o código de dentro: lê a etiqueta. E, como a etiqueta está colada no pote, ela vai junto para onde a função for: para outro arquivo que a importa, para o help(), para o editor de código que mostra a dica quando você digita o nome da função.
1. A primeira docstring
def troco(pago, total):
"""Devolve quanto de troco a Ana tem de dar."""
return pago - total
print(troco(20, 13.5))
- def troco(pago, total):
- Uma função comum (aula Funções).
- """
- Três aspas duplas abrem a docstring. É um texto (uma string) como outro qualquer, só que com aspas triplas, que permitem várias linhas.
- Devolve quanto de troco a Ana tem de dar.
- O que a função faz, numa frase. Costuma começar com um verbo ("Devolve", "Calcula", "Mostra") e terminar com ponto.
- """
- Três aspas fecham a docstring. Numa docstring de uma linha, abre e fecha na mesma linha.
- O lugar
- Tem de ser a primeira coisa dentro da função, logo abaixo do
def, com o mesmo recuo (4 espaços) do resto do corpo. Em qualquer outro lugar, não é docstring (veja Quando dá errado).
$ python3 troco.py 6.5
A docstring não muda nada no que a função faz: ela não aparece na saída nem atrapalha o return. Para que serve, então? Para ser lida, como você vai ver agora.
2. Lendo a documentação: help() e __doc__
A Ana guardou as funções da padaria num arquivo próprio, padaria.py, que outros programas podem importar (aula Criando seu Módulo):
"""Funções da padaria do bairro: preços e troco."""
def preco_com_desconto(preco, porcentagem):
"""Devolve o preço depois de aplicar o desconto.
preco: o preço original, em reais.
porcentagem: o desconto, de 0 a 100 (10 quer dizer 10%).
"""
return preco - preco * porcentagem / 100
def troco(pago, total):
"""Devolve quanto de troco a Ana tem de dar."""
return pago - total
help(): a ajuda do Python
A função embutida help() ("ajuda") mostra a documentação de qualquer coisa: uma função, um módulo inteiro. Ela monta a página com o nome, os parâmetros e a docstring:
$ python3 -c "import padaria; help(padaria.troco)"
Help on function troco in module padaria:
troco(pago, total)
Devolve quanto de troco a Ana tem de dar.
- Help on function troco in module padaria:
- "Ajuda sobre a função
troco, do módulopadaria." - troco(pago, total)
- O nome e os parâmetros, tirados do
def. Isso ohelp()descobre sozinho. - Devolve quanto de troco a Ana tem de dar.
- A docstring. Isso é o que só você pode escrever.
(O python3 -c "…" roda um programa de uma linha, escrito ali mesmo; é só um atalho para não criar mais um arquivo.) E com o módulo inteiro:
$ python3 -c "import padaria; help(padaria)"
Help on module padaria:
NAME
padaria - Funções da padaria do bairro: preços e troco.
FUNCTIONS
preco_com_desconto(preco, porcentagem)
Devolve o preço depois de aplicar o desconto.
preco: o preço original, em reais.
porcentagem: o desconto, de 0 a 100 (10 quer dizer 10%).
troco(pago, total)
Devolve quanto de troco a Ana tem de dar.
FILE
/home/ana/padaria.py
Uma página de manual completa, montada só com as docstrings: o NAME ("nome") usa a docstring do módulo (a primeira linha do arquivo), FUNCTIONS lista as funções com as suas docstrings, e FILE diz onde está o arquivo.
help() no modo interativo
No modo interativo (>>>), help() mostra o mesmo texto, mas numa tela à parte, para você poder rolar páginas longas com as setas. No terminal da Ana, depois de import padaria e help(padaria.preco_com_desconto), a última linha dessa tela é:
Help on preco_com_desconto line 1/7 (END) (press h for help or q to quit)
"(FIM) (aperte h para ajuda ou q para sair)". Aperte q para voltar ao >>>. Experimente com as funções embutidas: help(len), help(print).
__doc__: a docstring como texto
A docstring fica guardada num atributo da função chamado __doc__ (com dois sublinhados de cada lado; em inglês se lê "dunder doc"). Dá para mostrá-la com print:
import padaria
print(padaria.troco.__doc__)
print("---")
print(padaria.preco_com_desconto.__doc__)
print("---")
print(padaria.__doc__)
$ python3 usa_doc.py Devolve quanto de troco a Ana tem de dar. --- Devolve o preço depois de aplicar o desconto. preco: o preço original, em reais. porcentagem: o desconto, de 0 a 100 (10 quer dizer 10%). --- Funções da padaria do bairro: preços e troco.
Repare que os 4 espaços de recuo das linhas de dentro da docstring não aparecem: o Python tira o recuo em comum ao guardar o texto. A linha vazia antes do segundo --- é a última linha da docstring, a das três aspas sozinhas.
As funções embutidas também têm docstring (em inglês):
$ python3 -c "print(len.__doc__)" Return the number of items in a container.
"Devolve o número de itens de um contêiner." É daí que o help(len) tira o texto.
Missão: o print mostra None, porque a função não tem docstring. Escreva uma docstring de uma linha, com três aspas, dizendo Devolve a área do retângulo.
def area(largura, altura):
return largura * altura
print(area.__doc__)
def area(largura, altura):
"""Devolve a área do retângulo."""
return largura * altura
print(area.__doc__)
3. Docstring de várias linhas
Quando uma frase não basta, a docstring cresce. O costume da comunidade Python (descrito num documento chamado PEP 257) é:
- Primeira linha: um resumo curto, numa frase, logo depois das aspas de abertura.
- Uma linha em branco. Ela separa o resumo do resto; ferramentas como o
help()e os editores de código usam a primeira linha como resumo. - Os detalhes: o que é cada parâmetro, o que a função devolve, cuidados.
- As aspas de fechamento sozinhas na última linha.
def media(notas):
"""Devolve a média das notas, com uma casa decimal.
notas: uma lista de números de 0 a 10. Não pode estar vazia.
Devolve um float, por exemplo 7.3.
"""
return round(sum(notas) / len(notas), 1)
- O que a função faz e o que devolve, não como ela faz por dentro (isso o código já mostra).
- O que cada parâmetro espera: o tipo, a unidade (reais? centavos? de 0 a 100 ou de 0 a 1?), os limites.
- O que pode dar errado: "não pode estar vazia".
Uma docstring que só repete o nome da função ("""Função troco.""") não ajuda ninguém.
Muita gente coloca, na docstring, um exemplo de uso no formato do modo interativo (>>> troco(20, 13.5) e a resposta embaixo). O Python tem até uma ferramenta, o doctest, que roda esses exemplos e confere se a resposta continua certa. Ela é assunto da aula Testes.
4. Docstring do módulo
Um arquivo .py também pode ter docstring: é um texto entre três aspas na primeira linha do arquivo, antes de tudo (antes até dos import). Foi o que a Ana fez no padaria.py:
"""Funções da padaria do bairro: preços e troco."""
Ela aparece no help(padaria), na linha NAME, e em padaria.__doc__. As classes (aula Classes e Objetos) também têm docstring, logo abaixo da linha class, do mesmo jeito.
Formas diferentes de fazer a mesma coisa
| Forma | Exemplo | Quando usar |
|---|---|---|
| Docstring de uma linha | """Devolve o troco.""" | Funções simples, em que uma frase explica tudo |
| Docstring de várias linhas | Resumo, linha em branco, detalhes | Quando há parâmetros que precisam de explicação, unidades, limites |
Comentário # | # o desconto vem em porcentagem | Para explicar como uma linha do código funciona, para quem lê o código (aula Comentários). Não aparece no help() |
''' (aspas simples triplas) | '''Devolve o troco.''' | Funciona igual, mas o costume (PEP 257) é """. Prefira """ |
| Uma aspa só | "Devolve o troco." | Também vira docstring se estiver no lugar certo, mas não aceita várias linhas. Prefira """ sempre |
A docstring é para quem vai usar a função (o que ela faz); o comentário é para quem vai mexer no código (como ele faz). Veja a diferença no help() logo abaixo, em Quando dá errado.
Quando dá errado
def troco(pago, total):
# Devolve quanto de troco a Ana tem de dar.
return pago - total
print(troco.__doc__)
help(troco)
$ python3 comentario.py None Help on function troco in module __main__: troco(pago, total)
Não há erro, mas a explicação sumiu: __doc__ vale None ("nada", aula O Valor None), e o help() mostra só o nome e os parâmetros. O Python joga fora os comentários ao ler o programa; eles não ficam guardados em lugar nenhum. (__main__ é o nome que o Python dá ao arquivo que você mandou rodar.) Como consertar: troque o # por uma docstring: """Devolve quanto de troco a Ana tem de dar.""".
def troco(pago, total):
resultado = pago - total
"""Devolve quanto de troco a Ana tem de dar."""
return resultado
print(troco.__doc__)
$ python3 fora_do_lugar.py None
De novo None, e sem erro. O texto entre aspas está lá, mas não é a primeira coisa do corpo da função: veio depois do resultado = …. Aí ele vira só um texto solto, que o Python calcula e descarta. Como consertar: a docstring vai logo abaixo do def, antes de qualquer outra linha.
Missão: o programa mostra None em vez da documentação. Mova a docstring para o lugar certo.
def troco(pago, total):
resultado = pago - total
"""Devolve quanto de troco a Ana tem de dar."""
return resultado
print(troco.__doc__)
def troco(pago, total):
"""Devolve quanto de troco a Ana tem de dar."""
resultado = pago - total
return resultado
print(troco.__doc__)
def troco(pago, total):
"""Devolve quanto de troco a Ana tem de dar."""
return pago - total
$ python3 sem_recuo.py
File "/home/ana/sem_recuo.py", line 2
"""Devolve quanto de troco a Ana tem de dar."""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after function definition on line 1
"Erro de indentação: esperava um bloco recuado depois da definição de função da linha 1." A docstring faz parte do corpo da função, então precisa do mesmo recuo de 4 espaços (aula Sintaxe e Indentação). Repare que não há Traceback: o Python nem começou a rodar o programa, porque não conseguiu nem ler o arquivo. Como consertar: 4 espaços antes das aspas.
Uma aspa só não aceita quebra de linha:
def troco(pago, total):
"Devolve quanto de troco
a Ana tem de dar."
return pago - total
$ python3 aspas_simples.py
File "/home/ana/aspas_simples.py", line 2
"Devolve quanto de troco
^
SyntaxError: unterminated string literal (detected at line 2)
"Texto não terminado (detectado na linha 2)": a aspa abriu e a linha acabou sem fechá-la. E quando as três aspas abrem, mas a pessoa esquece de fechar:
def troco(pago, total):
"""Devolve quanto de troco a Ana tem de dar.
return pago - total
print(troco(20, 13.5))
$ python3 aspas_fim.py
File "/home/ana/aspas_fim.py", line 2
"""Devolve quanto de troco a Ana tem de dar.
^
SyntaxError: unterminated triple-quoted string literal (detected at line 6)
"Texto de aspas triplas não terminado (detectado na linha 6)". O Python foi engolindo tudo como parte do texto, o return e o print inclusive, até o fim do arquivo (linha 6), procurando as três aspas de fechamento. O ^ aponta para onde o texto começou, que é onde você deve procurar. Como consertar: feche com """ no fim da docstring.
Referência rápida
| Escrita | O que faz |
|---|---|
"""Resumo em uma linha.""" logo abaixo do def | Docstring de uma linha |
"""Resumo. / linha em branco / detalhes / """ | Docstring de várias linhas (PEP 257) |
"""…""" na primeira linha do arquivo | Docstring do módulo |
help(funcao) | Mostra a página de ajuda (nome, parâmetros, docstring) |
help(modulo) | Mostra a ajuda do módulo inteiro |
funcao.__doc__ | A docstring como texto (None se não houver) |
| q | Sai da tela do help() no modo interativo |
| Sintoma | Causa provável |
|---|---|
__doc__ vale None, help() sem descrição | Não há docstring: foi usado #, ou o texto não é a primeira linha do corpo |
IndentationError: expected an indented block after function definition | A docstring (ou o corpo) sem os 4 espaços de recuo |
SyntaxError: unterminated string literal | Docstring de várias linhas com uma aspa só: use """ |
SyntaxError: unterminated triple-quoted string literal | Faltou fechar o """ |
Exercícios
1. As aspas
Complete a docstring de uma linha (as aspas de abrir e de fechar são iguais):
2. O atributo
Complete para mostrar a docstring da função dobro:
3. Onde fica a docstring de uma função?
4. A função tem só um comentário # Calcula o troco. logo abaixo do def. O que print(troco.__doc__) mostra?
5. Pelo costume da PEP 257, o que vem logo depois da primeira linha (o resumo) numa docstring de várias linhas?
Missão final: documentando a média
Missão: escreva uma docstring de várias linhas para a função media: na primeira linha, o resumo Devolve a média das notas.; depois, uma linha em branco; depois, pelo menos uma linha explicando o parâmetro notas.
def media(notas):
return sum(notas) / len(notas)
print(media.__doc__)
def media(notas):
"""Devolve a média das notas.
notas: uma lista de números de 0 a 10. Não pode estar vazia.
"""
return sum(notas) / len(notas)
print(media.__doc__)
Resumo
- A docstring é um texto entre
"""que fica logo abaixo dodef, como primeira coisa do corpo, com o mesmo recuo. - Ela explica o que a função faz, o que espera e o que devolve, para quem vai usá-la. O comentário
#explica como, para quem vai mexer no código. - Uma linha:
"""Devolve o troco.""". Várias linhas: resumo, linha em branco, detalhes,"""sozinho no fim (PEP 257). help(funcao)mostra a página de ajuda; no modo interativo, saia com q.funcao.__doc__devolve o texto, ouNone.- Um texto entre aspas na primeira linha do arquivo é a docstring do módulo.
- Fora do lugar ou com
#, não é docstring:None, sem erro. Sem recuo,IndentationError; sem fechar,SyntaxError: unterminated ….