Tutorial Python
Tutorial Python
Release 3.9.1
5 Estruturas de dados 33
5.1 Mais sobre listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.1.1 Usando listas como pilhas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.1.2 Usando listas como filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.1.3 Compreensões de lista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.1.4 Compreensões de lista aninhadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.2 A instrução del . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
i
5.3 Tuplas e sequências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.4 Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.5 Dicionários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.6 Técnicas de iteração . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.7 Mais sobre condições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.8 Comparando sequências e outros tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6 Módulos 45
6.1 Mais sobre módulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6.1.1 Executando módulos como scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.1.2 O caminho de busca dos módulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.1.3 Arquivos Python “compilados” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.2 Módulos padrões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.3 A função dir() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.4 Pacotes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.4.1 Importando * de um pacote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.4.2 Referências em um mesmo pacote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
6.4.3 Pacotes em múltiplos diretórios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7 Entrada e saída 55
7.1 Refinando a formatação de saída . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7.1.1 Strings literais formatadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.1.2 O método format() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.1.3 Formatação manual de string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.1.4 Formatação de strings à moda antiga . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.2 Leitura e escrita de arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
7.2.1 Métodos de objetos arquivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.2.2 Gravando dados estruturados com json . . . . . . . . . . . . . . . . . . . . . . . . . . 61
8 Erros e exceções 63
8.1 Erros de sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.2 Exceções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8.3 Tratamento de exceções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
8.4 Levantando exceções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
8.5 Encadeamento de exceções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
8.6 Exceções definidas pelo usuário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.7 Definindo ações de limpeza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.8 Ações de limpeza predefinidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9 Classes 71
9.1 Uma palavra sobre nomes e objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.2 Escopos e espaços de nomes do Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.2.1 Exemplo de escopos e espaço de nomes . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
9.3 Uma primeira olhada nas classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
9.3.1 Sintaxe da definição de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
9.3.2 Objetos classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
9.3.3 Objetos instância . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.3.4 Objetos método . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
9.3.5 Variáveis de classe e instância . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
9.4 Observações aleatórias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
9.5 Herança . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
9.5.1 Herança múltipla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
9.6 Variáveis privadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
9.7 Curiosidades e conclusões . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
9.8 Iteradores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
9.9 Geradores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
9.10 Expressões geradoras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
ii
10.1 Interface com o sistema operacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.2 Caracteres curinga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
10.3 Argumentos de linha de comando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
10.4 Redirecionamento de erros e encerramento do programa . . . . . . . . . . . . . . . . . . . . . . 86
10.5 Reconhecimento de padrões em strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
10.6 Matemática . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
10.7 Acesso à internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
10.8 Data e hora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10.9 Compressão de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
10.10 Medição de desempenho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
10.11 Controle de qualidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
10.12 Baterias incluídas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
13 E agora? 103
16 Anexo 113
16.1 Modo interativo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
16.1.1 Tratamento de erros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
16.1.2 Scripts Python executáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
16.1.3 Arquivo de inicialização do modo interativo . . . . . . . . . . . . . . . . . . . . . . . . 114
16.1.4 Módulos de customização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
A Glossário 115
iii
C.3.2 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
C.3.3 Serviços de soquete assíncrono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
C.3.4 Gerenciamento de cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
C.3.5 Rastreamento de execução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
C.3.6 Funções UUencode e UUdecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
C.3.7 Chamadas de Procedimento Remoto XML . . . . . . . . . . . . . . . . . . . . . . . . . 139
C.3.8 test_epoll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
C.3.9 Selecione o kqueue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
C.3.10 SipHash24 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
C.3.11 strtod e dtoa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
C.3.12 OpenSSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
C.3.13 expat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
C.3.14 libffi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
C.3.15 zlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
C.3.16 cfuhash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
C.3.17 libmpdec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
C.3.18 Conjunto de testes C14N do W3C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Índice 151
iv
Python Tutorial, Release 3.9.1
Python é uma linguagem fácil de aprender e poderosa. Ela tem estruturas de dados de alto nível eficientes e uma
abordagem simples mas efetiva de programação orientada a objetos. A elegância de sintaxe e a tipagem dinâmica
do Python aliadas com sua natureza interpretativa, o fazem a linguagem ideal para programas e desenvolvimento de
aplicações rápidas em diversas áreas e na maioria das plataformas.
O interpretador Python e a extensiva biblioteca padrão estão disponíveis gratuitamente em código ou na forma binária
para toda as maiores plataformas no endereço eletrônico do Python, https://www.python.org/, e pode ser livremente
distribuído. O mesmo endereço contém distribuições de diversos módulos, programas e ferramentas gratuitos pro-
duzidos por terceiros e documentação adicional.
O interpretador Python pode ser facilmente estendido com novas funções e tipos de dados implementados em C ou
C++ (ou outras linguagens chamadas a partir de C). Python também é adequada como uma linguagem de extensão
para aplicações personalizáveis.
Este tutorial introduz informalmente o leitor aos conceitos básicos e aos recursos da linguagem e do sistema Python. É
mais fácil se você possuir um interpretador Python para uma experiência prática, mas os exemplos são autossuficientes
e, portanto, o tutorial pode apenas ser lido off-line também.
Para uma descrição detalhada dos módulos e objetos padrões, veja library-index. Em reference-index você encontra
uma definição mais formal da linguagem. Para escrever extensões em C ou C++ leia extending-index e c-api-index.
Existe também uma série de livros que cobrem Python em profundidade.
Este tutorial não espera ser abrangente e cobrir todos os recursos ou mesmo os recursos mais usados. Ele busca
introduzir diversos dos recursos mais notáveis do Python e lhe dará uma boa ideia do sabor e estilo da linguagem.
Depois de lê-lo, você terá condições de ler e escrever programas e módulos Python e estará pronto para aprender
mais sobre os diversos módulos descritos em library-index.
O Glossário também vale a pena ser estudado.
Sumário 1
Python Tutorial, Release 3.9.1
2 Sumário
CAPÍTULO 1
Se você trabalha muito com computadores, acabará encontrando alguma tarefa que gostaria de automatizar. Por
exemplo, você pode querer fazer busca-e-troca em um grande número de arquivos de texto, ou renomear e reorganizar
um monte de arquivos de fotos de uma maneira complicada. Talvez você gostaria de escrever um pequeno banco de
dados personalizado, ou um aplicativo GUI especializado, ou um jogo simples.
Se você é um desenvolvedor de software profissional, pode ter que trabalhar com várias bibliotecas C/C++/Java, mas
o tradicional ciclo escrever/compilar/testar/recompilar é muito lento. Talvez você esteja escrevendo um conjunto de
testes para uma biblioteca e está achando tedioso codificar os testes. Ou talvez você tenha escrito um programa que
poderia utilizar uma linguagem de extensão, e você não quer conceber e implementar toda uma nova linguagem para
sua aplicação.
Python é a linguagem para você.
Você poderia escrever um script para o shell do Unix ou arquivos em lote do Windows para algumas dessas tarefas,
mas scripts shell são bons para mover arquivos e alterar textos, mas não adequados para aplicações GUI ou jogos.
Você poderia escrever um programa em C/C++/Java, mas pode tomar tempo de desenvolvimento para chegar até um
primeiro rascunho. Python é mais simples, está disponível em Windows, Mac OS X, e sistemas operacionais Unix,
e vai ajudá-lo a fazer o trabalho mais rapidamente.
Python é fácil de usar, sem deixar de ser uma linguagem de programação de verdade, oferecendo muito mais estru-
turação e suporte para programas extensos do que shell scripts ou arquivos de lote oferecem. Por outro lado, Python
também oferece melhor verificação de erros do que C, e por ser uma linguagem de muito alto nível, ela possui tipos
nativos de alto nível, tais como dicionários e vetores (arrays) flexíveis. Devido ao suporte nativo a uma variedade
de tipos de dados, Python é aplicável a um domínio de problemas muito mais vasto do que Awk ou até mesmo Perl,
ainda assim muitas tarefas são pelo menos tão fáceis em Python quanto nessas linguagens.
Python permite que você organize seu programa em módulos que podem ser reutilizados em outros programas escritos
em Python. A linguagem provê uma vasta coleção de módulos que podem ser utilizados como base para sua aplicação
— ou como exemplos para estudo e aprofundamento. Alguns desses módulos implementam manipulação de arquivos,
chamadas do sistema, sockets, e até mesmo acesso a bibliotecas de construção de interfaces gráficas, como Tk.
Python é uma linguagem interpretada, por isso você pode economizar um tempo considerável durante o desenvol-
vimento, uma vez que não há necessidade de compilação e vinculação (linking). O interpretador pode ser usado
interativamente, o que torna fácil experimentar diversas características da linguagem, escrever programas “descar-
táveis”, ou testar funções em um desenvolvimento debaixo para cima (bottom-up). É também uma útil calculadora
de mesa.
Python permite a escrita de programas compactos e legíveis. Programas escritos em Python são tipicamente mais
curtos do que seus equivalentes em C, C++ ou Java, por diversas razões:
3
Python Tutorial, Release 3.9.1
• os tipos de alto nível permitem que você expresse operações complexas em um único comando;
• a definição de bloco é feita por indentação ao invés de marcadores de início e fim de bloco;
• não há necessidade de declaração de variáveis ou parâmetros formais;
Python é extensível: se você sabe como programar em C, é fácil adicionar funções ou módulos diretamente no
interpretador, seja para desempenhar operações críticas em máxima velocidade, ou para vincular programas Python
a bibliotecas que só estejam disponíveis em formato binário (como uma biblioteca gráfica de terceiros). Uma vez que
você tenha sido fisgado, você pode vincular o interpretador Python a uma aplicação escrita em C e utilizá-la como
linguagem de comandos ou extensão para esta aplicação.
A propósito, a linguagem foi batizada a partir do famoso programa da BBC “Monty Python’s Flying Circus” e não
tem nada a ver com répteis. Fazer referências a citações do programa na documentação não é só permitido, como
também é encorajado!
Agora que você está entusiasmado com Python, vai querer conhecê-la com mais detalhes. Partindo do princípio que
a melhor maneira de aprender uma linguagem é usando-a, você está agora convidado a fazê-lo com este tutorial.
No próximo capítulo, a mecânica de utilização do interpretador é explicada. Essa informação, ainda que mundana, é
essencial para a experimentação dos exemplos apresentados mais tarde.
O resto do tutorial introduz diversos aspectos do sistema e linguagem Python por intermédio de exemplos. Serão
abordadas expressões simples, comandos, tipos, funções e módulos. Finalmente, serão explicados alguns conceitos
avançados como exceções e classes definidas pelo usuário.
python3.9
no shell.1 Considerando que a escolha do diretório onde o interpretador está é uma opção de instalação, outros locais
são possíveis; verifique com seu guru local de Python ou administrador do sistema local. (Por exemplo, /usr/
local/python é um local alternativo popular.)
Em máquinas Windows onde você instalou Python a partir da Microsoft Store, o comando python3.9 estará
disponível. Se você tem o lançador py.exe instalado, você pode usar o comando py. Veja setting-envvars para outras
maneiras de executar o Python.
Digitando um caractere de fim-de-arquivo (Control-D no Unix, Control-Z no Windows) diretamente no
prompt força o interpretador a sair com status de saída zero. Se isso não funcionar, você pode sair do interpre-
tador digitando o seguinte comando: quit().
Os recursos de edição de linha do interpretador incluem edição interativa, substituição de histórico e complemento de
código, em sistemas com suporte à biblioteca GNU Readline. Talvez a verificação mais rápida para ver se o suporte à
edição de linha de comando está disponível é digitando Control-P no primeiro prompt oferecido pelo Python. Se
for emitido um bipe, você terá a edição da linha de comando; veja Apêndice Edição de entrada interativa e substituição
de histórico para uma introdução às combinações. Se nada acontecer, ou se ^P aparecer na tela, a edição da linha de
comando não está disponível; você só poderá usar backspace para remover caracteres da linha atual.
O interpretador trabalha de forma semelhante a uma shell de Unix: quando chamado com a saída padrão conectada
a um console de terminal, ele lê e executa comandos interativamente; quando chamado com um nome de arquivo
como argumento, ou com redirecionamento da entrada padrão para ler um arquivo, o interpretador lê e executa o
script contido no arquivo.
Uma segunda forma de rodar o interpretador é python -c command [arg] ..., que executa um ou mais
comandos especificados na posição comando, analogamente à opção de shell -c. Considerando que comandos Python
frequentemente têm espaços em branco (ou outros caracteres que são especiais para a shell) é aconselhável que o
comando esteja dentro de aspas duplas.
1 No Unix, o interpretador Python 3.x não é instalado por padrão com o executável nomeado python, então não vai conflitar com um
5
Python Tutorial, Release 3.9.1
Alguns módulos Python são também úteis como scripts. Estes podem ser chamados usando python -m modulo
[arg] ..., que executa o arquivo fonte do módulo como se você tivesse digitado seu caminho completo na linha
de comando.
Quando um arquivo de script é utilizado, às vezes é útil executá-lo e logo em seguida entrar em modo interativo. Isto
pode ser feito acrescentando o argumento -i antes do nome do script.
Todas as opções de linha de comando são descritas em using-on-general.
Quando são de conhecimento do interpretador, o nome do script e demais argumentos da linha de comando da
shell são acessíveis ao próprio script através da variável argv do módulo sys. Pode-se acessar essa lista executando
import sys. Essa lista tem sempre ao menos um elemento; quando nenhum script ou argumento for passado para
o interpretador, sys.argv[0] será uma string vazia. Quando o nome do script for '-' (significando entrada pa-
drão), o conteúdo de sys.argv[0] será '-'. Quando for utilizado -c comando, sys.argv[0] conterá '-c'.
Quando for utilizado -m módulo, sys.argv[0] conterá o caminho completo do módulo localizado. Opções es-
pecificadas após -c comando ou -m módulo não serão consumidas pelo interpretador mas deixadas em sys.argv
para serem tratadas pelo comando ou módulo.
Quando os comandos são lidos a partir do console, diz-se que o interpretador está em modo interativo. Nesse modo
ele solicita um próximo comando através do prompt primário, tipicamente três sinais de maior (>>>); para linhas de
continuação do comando atual, o prompt secundário padrão é formado por três pontos (...). O interpretador exibe
uma mensagem de boas vindas, informando seu número de versão e um aviso de copyright antes de exibir o primeiro
prompt:
$ python3.9
Python 3.9 (default, June 4 2019, 09:25:04)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Linhas de continuação são necessárias em construções multi-linha. Como exemplo, dê uma olhada nesse comando
if:
Por padrão, arquivos fonte de Python são tratados com codificação UTF-8. Nessa codificação, caracteres de muitos
idiomas no mundo podem ser usados simultaneamente em literais string, identificadores e comentários — embora
a biblioteca padrão use apenas caracteres ASCII para identificadores, uma convenção que qualquer código portável
deve seguir. Para exibir todos esses caracteres corretamente, seu editor deve reconhecer que o arquivo é UTF-8 e
deve usar uma fonte com suporte a todos os caracteres no arquivo.
Para declarar uma codificação diferente da padrão, uma linha de comentário especial deve ser adicionada como
primeira linha do arquivo. A sintaxe é essa:
Uma exceção para a regra da primeira linha é quando o código-fonte inicia com uma linha com UNIX “shebang”.
Nesse caso, a declaração de codificação deve ser adicionada como a segunda linha do arquivo. Por exemplo:
#!/usr/bin/env python3
# -*- coding: cp1252 -*-
Nos exemplos seguintes, pode-se distinguir entrada e saída pela presença ou ausência dos prompts (»> e …): para
repetir o exemplo, você deve digitar tudo após o prompt, quando o mesmo aparece; linhas que não começarem com
um prompt são na verdade as saídas geradas pelo interpretador. Observe que quando aparece uma linha contendo
apenas o prompt secundário você deve digitar uma linha em branco; é assim que se encerra um comando de múltiplas
linhas.
Muitos dos exemplos neste manual, até mesmo aqueles digitados interativamente, incluem comentários. Comentários
em Python são iniciados pelo caractere #, e se estendem até o final da linha física. Um comentário pode aparecer
no início da linha, depois de um espaço em branco ou código, mas nunca dentro de uma string literal. O caractere #
em uma string literal não passa de um caractere #. Uma vez que os comentários são usados apenas para explicar o
código e não são interpretados pelo Python, eles podem ser omitidos ao digitar os exemplos.
Alguns exemplos:
Vamos experimentar alguns comandos simples em Python. Inicie o interpretador e aguarde o prompt primário, >>>.
(Não deve demorar muito.)
3.1.1 Números
O interpretador funciona como uma calculadora bem simples: você pode digitar uma expressão e o resultado será
apresentado. A sintaxe de expressões é a usual: operadores +, -, * e / funcionam da mesma forma que em outras
linguagens tradicionais (por exemplo, Pascal ou C); parênteses (()) podem ser usados para agrupar expressões. Por
exemplo:
>>> 2 + 2
4
>>> 50 - 5*6
(continua na próxima página)
9
Python Tutorial, Release 3.9.1
Os números inteiros (ex. 2, 4, 20) são do tipo int, aqueles com parte fracionária (ex. 5.0, 1.6) são do tipo
float. Veremos mais sobre tipos numéricos posteriormente neste tutorial.
Divisão (/) sempre retorna ponto flutuante (float). Para fazer uma divisão pelo piso e receber um inteiro como
resultado (descartando a parte fracionária) você pode usar o operador //; para calcular o resto você pode usar o %:
>>> 5 ** 2 # 5 squared
25
>>> 2 ** 7 # 2 to the power of 7
128
O sinal de igual ('=') é usado para atribuir um valor a uma variável. Depois de uma atribuição, nenhum resultado é
exibido antes do próximo prompt:
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
Se uma variável não é “definida” (não tem um valor atribuído), tentar utilizá-la gerará um erro:
Há suporte completo para ponto flutuante (float); operadores com operandos de diferentes tipos convertem o inteiro
para ponto flutuante:
>>> 4 * 3.75 - 1
14.0
No modo interativo, o valor da última expressão exibida é atribuída a variável _. Assim, ao utilizar Python como
uma calculadora, fica mais fácil prosseguir com os cálculos, por exemplo:
Essa variável especial deve ser tratada como somente para leitura pelo usuário. Nunca lhe atribua explicitamente
um valor — do contrário, estaria criando uma outra variável (homônima) independente, que mascararia a variável
especial com seu comportamento mágico.
Além de int e float, o Python suporta outros tipos de números, tais como Decimal e Fraction. O Python
também possui suporte nativo a números complexos, e usa os sufixos j ou J para indicar a parte imaginária (por
exemplo, 3+5j).
3.1.2 Strings
Além de números, Python também pode manipular strings (sequências de caracteres), que podem ser expressas de
diversas formas. Elas podem ser delimitadas por aspas simples ('...') ou duplas ("...") e teremos o mesmo
resultado2 . \ pode ser usada para escapar aspas:
Na interpretação interativa, a string de saída é delimitada com aspas e caracteres especiais são escapados com barras
invertidas. Embora isso possa às vezes parecer diferente da entrada (as aspas podem mudar), as duas strings são
equivalentes. A string é delimitada com aspas duplas se a string contiver uma única aspa simples e nenhuma aspa
dupla, caso contrário, ela é delimitada com aspas simples. A função print() produz uma saída mais legível, ao
omitir as aspas e ao imprimir caracteres escapados e especiais:
Se não quiseres que os caracteres sejam precedidos por \ para serem interpretados como caracteres especiais, poderás
usar strings raw (N.d.T: “crua” ou sem processamento de caracteres de escape) adicionando um r antes da primeira
aspa:
2 Ao contrário de outras linguagens, caracteres especiais como \n têm o mesmo significado com as aspas simples ('...') e duplas ("...")
. A única diferença entre as duas é que, dentro de aspas simples, você não precisa escapar o " (mas você deve escapar a \') e vice-versa.
As strings literais podem abranger várias linhas. Uma maneira é usar as aspas triplas: """...""" ou '''...
'''. O fim das linhas é incluído automaticamente na string, mas é possível evitar isso adicionando uma \ no final.
O seguinte exemplo:
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
produz a seguinte saída (observe que a linha inicial não está incluída):
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
Duas ou mais strings literais (ou seja, entre aspas) ao lado da outra são automaticamente concatenados.
>>> 'Py' 'thon'
'Python'
Esse recurso é particularmente útil quando você quer quebrar strings longas:
>>> text = ('Put several strings within parentheses '
... 'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
Isso só funciona com duas strings literais, não com variáveis ou expressões:
>>> prefix = 'Py'
>>> prefix 'thon' # can't concatenate a variable and a string literal
File "<stdin>", line 1
prefix 'thon'
^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^
SyntaxError: invalid syntax
As strings podem ser indexadas (subscritas), com o primeiro caractere como índice 0. Não existe um tipo específico
para caracteres; um caractere é simplesmente uma string cujo tamanho é 1:
>>> word = 'Python'
>>> word[0] # character in position 0
'P'
>>> word[5] # character in position 5
'n'
Índices também podem ser números negativos para iniciar a contagem pela direita:
Note que dado que -0 é o mesmo que 0, índices negativos começam em -1.
Além da indexação, o fatiamento também é permitido. Embora a indexação seja usada para obter caracteres indivi-
duais, fatiar permite que você obtenha substring:
Observe como o início sempre está incluído, e o fim sempre é excluído. Isso garante que s[:i] + s[i:] seja
sempre igual a s:
Os índices do fatiamento possuem padrões úteis; um primeiro índice omitido padrão é zero, um segundo índice
omitido é por padrão o tamanho da string sendo fatiada:
Uma maneira de lembrar como fatias funcionam é pensar que os índices indicam posições entre caracteres, onde a
borda esquerda do primeiro caractere é 0. Assim, a borda direita do último caractere de uma string de comprimento
n tem índice n, por exemplo:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
A primeira fileira de números indica a posição dos índices 0…6 na string; a segunda fileira indica a posição dos
respectivos índices negativos. Uma fatia de i a j consiste em todos os caracteres entre as bordas i e j, respectivamente.
Para índices positivos, o comprimento da fatia é a diferença entre os índices, se ambos estão dentro dos limites da
string. Por exemplo, o comprimento de word[1:3] é 2.
A tentativa de usar um índice que seja muito grande resultará em um erro:
No entanto, os índices de fatiamento fora do alcance são tratados graciosamente (N.d.T: o termo original “gracefully”
indica robustez no tratamento de erros) quando usados para fatiamento. Um índice maior que o comprimento é
trocado pelo comprimento, um limite superior menor que o limite inferior produz uma string vazia:
>>> word[4:42]
'on'
>>> word[42:]
''
As strings do Python não podem ser alteradas — uma string é imutável. Portanto, atribuir a uma posição indexada
na sequência resulta em um erro:
>>> s = 'supercalifragilisticexpialidocious'
>>> len(s)
34
Ver também:
textseq As strings são exemplos de tipos de sequências e suportam as operações comumente suportadas por esses
tipos.
string-methods As strings suportam uma grande quantidade de métodos para transformações básicas e busca.
f-strings Strings literais que possuem expressões embutidas.
formatstrings Informações sobre formatação de string com o método str.format().
old-string-formatting As antigas operações de formatação invocadas quando as strings são o operando esquerdo
do operador % são descritas com mais detalhes aqui.
3.1.3 Listas
Python inclui diversas estruturas de dados compostas, usadas para agrupar outros valores. A mais versátil é list (lista),
que pode ser escrita como uma lista de valores (itens) separados por vírgula, entre colchetes. Os valores contidos na
lista não precisam ser todos do mesmo tipo.
Como strings (e todos os tipos embutidos de sequência), listas pode ser indexados e fatiados:
Todas as operações de fatiamento devolvem uma nova lista contendo os elementos solicitados. Isso significa que o
seguinte fatiamento devolve uma cópia rasa da lista:
>>> squares[:]
[1, 4, 9, 16, 25]
Diferentemente de strings, que são imutáveis, listas são mutáveis, ou seja, é possível alterar elementos individuais de
uma lista:
Você também pode adicionar novos itens no final da lista, usando o método append() (estudaremos mais a respeito
dos métodos posteriormente):
Atribuição a fatias também é possível, e isso pode até alterar o tamanho da lista ou remover todos os itens dela:
É possível aninhar listas (criar listas contendo outras listas), por exemplo:
Claro, podemos usar o Python para tarefas mais complicadas do que somar 2+2. Por exemplo, podemos escrever o
início da sequência de Fibonacci assim:
>>> i = 256*256
>>> print('The value of i is', i)
The value of i is 65536
O argumento end pode ser usado para evitar uma nova linha após a saída ou finalizar a saída com uma string
diferente:
>>> a, b = 0, 1
>>> while a < 1000:
(continua na próxima página)
Além do comando while recém apresentado, Python tem as estruturas usuais de controle de fluxo conhecidas em
outras linguagens, com algumas particulares.
4.1 Comandos if
Pode haver zero ou mais partes elif, e a parte else é opcional. A palavra-chave ‘elif’ é uma abreviação para
‘else if’, e é útil para evitar indentação excessiva. Uma sequência if … elif … elif … substitui os comandos
switch ou case, encontrados em outras linguagens.
19
Python Tutorial, Release 3.9.1
O comando for em Python é um pouco diferente do que costuma ser em C ou Pascal. Ao invés de sempre iterar
sobre uma progressão aritmética de números (como no Pascal), ou permitir ao usuário definir o passo de iteração e a
condição de parada (como C), o comando for do Python itera sobre os itens de qualquer sequência (seja uma lista
ou uma string), na ordem que aparecem na sequência. Por exemplo:
Código que modifica uma coleção sobre a qual está iterando pode ser inseguro. No lugar disso, usualmente você deve
iterar sobre uma cópia da coleção ou criar uma nova coleção:
Se você precisa iterar sobre sequências numéricas, a função embutida range() é a resposta. Ela gera progressões
aritméticas:
O ponto de parada fornecido nunca é incluído na lista; range(10) gera uma lista com 10 valores, exatamente os
índices válidos para uma sequência de comprimento 10. É possível iniciar o intervalo com outro número, ou alterar
a razão da progressão (inclusive com passo negativo):
range(5, 10)
5, 6, 7, 8, 9
range(0, 10, 3)
0, 3, 6, 9
Para iterar sobre os índices de uma sequência, combine range() e len() da seguinte forma:
Na maioria dos casos, porém, é mais conveniente usar a função enumerate(), veja Técnicas de iteração.
Uma coisa estranha acontece se você imprime um intervalo:
>>> print(range(10))
range(0, 10)
Em muitos aspectos, o objeto retornado pela função range() se comporta como se fosse uma lista, mas na verdade
não é. É um objeto que retorna os itens sucessivos da sequência desejada quando você itera sobre a mesma, mas na
verdade ele não gera a lista, economizando espaço.
Dizemos que um objeto é iterável, isso é, candidato a ser alvo de uma função ou construção que espera alguma coisa
capaz de retornar sucessivamente seus elementos um de cada vez. Nós vimos que o comando for é um exemplo de
construção, enquanto que um exemplo de função que recebe um iterável é sum():
>>> sum(range(4)) # 0 + 1 + 2 + 3
6
Mais tarde, veremos mais funções que retornam e recebem iteráveis como argumentos. Por último, você deve estar
curioso sobre como pegar uma lista de um intervalo. Aqui está a solução:
>>> list(range(4))
[0, 1, 2, 3]
O comando break, como no C, sai imediatamente do laço de repetição mais interno, seja for ou while.
Laços podem ter uma cláusula else, que é executada sempre que o laço se encerra por exaustão do iterável (no caso
do for) ou quando a condição se torna falsa (no caso do while), mas nunca quando o laço é interrompido por um
break. Isto é exemplificado no próximo exemplo que procura números primos:
(Sim, o código está correto. Olhe atentamente: a cláusula else pertence ao laço for, e não ao comando if.)
Quando usado em um laço, a cláusula else tem mais em comum com a cláusula else de um comando try do que
com a de um comando if: a cláusula else de um comando try executa quando não ocorre exceção, e o else
de um laço executa quando não ocorre um break. Para mais informações sobre comando try e exceções, veja
Tratamento de exceções.
A instrução continue, também emprestada da linguagem C, continua com a próxima iteração do laço:
O comando pass não faz nada. Pode ser usada quando a sintaxe exige um comando mas a semântica do programa
não requer nenhuma ação. Por exemplo:
Outra ocasião em que o pass pode ser usado é como um substituto temporário para uma função ou bloco condicional,
quando se está trabalhando com código novo, ainda indefinido, permitindo que mantenha-se o pensamento num nível
mais abstrato. O pass é silenciosamente ignorado:
Podemos criar uma função que escreve a série de Fibonacci até um limite arbitrário:
A palavra reservada def inicia a definição de uma função. Ela deve ser seguida do nome da função e da lista de
parâmetros formais entre parênteses. Os comandos que formam o corpo da função começam na linha seguinte e
devem ser indentados.
Opcionalmente, a primeira linha do corpo da função pode ser uma literal string, cujo propósito é documentar a função.
Se presente, essa string chama-se docstring. (Há mais informação sobre docstrings na seção Strings de documentação.)
Existem ferramentas que utilizam docstrings para produzir automaticamente documentação online ou para imprimir,
ou ainda, permitir que o usuário navegue interativamente pelo código. É uma boa prática incluir sempre docstrings
em suas funções, portanto, tente fazer disso um hábito.
A execução de uma função cria uma nova tabela de símbolos para as variáveis locais da função. Mais precisamente,
todas as atribuições de variáveis numa função são armazenadas na tabela de símbolos local; referências a variáveis são
buscadas primeiro na tabela de símbolos local, em seguida na tabela de símbolos locais de funções delimitadoras ou
circundantes, depois na tabela de símbolos global e, finalmente, na tabela de nomes da própria linguagem. Embora
possam ser referenciadas, variáveis globais e de funções externas não podem ter atribuições (a menos que seja utilizado
o comando global, para variáveis globais, ou nonlocal, para variáveis de funções externas).
Os parâmetros reais (argumentos) de uma chamada de função são introduzidos na tabela de símbolos local da função
no momento da chamada; portanto, argumentos são passados por valor (onde o valor é sempre uma referência para
objeto, não o valor do objeto).1 Quando uma função chama outra função, uma nova tabela de símbolos é criada para
tal chamada.
Uma definição de função associa o nome da função com o objeto função na tabela de símbolos atual. O interpretador
reconhece o objeto apontado pelo nome como uma função definida pelo usuário. Outros nomes também podem
apontar para o mesmo objeto função e também pode ser usados pra acessar a função:
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
Conhecendo outras linguagens, pode-se questionar que fib não é uma função, mas um procedimento, pois ela não
devolve um valor. Na verdade, mesmo funções que não usam o comando return devolvem um valor, ainda que
pouco interessante. Esse valor é chamado None (é um nome embutido). O interpretador interativo evita escrever
None quando ele é o único resultado de uma expressão. Mas se quiser vê-lo pode usar a função print():
>>> fib(0)
>>> print(fib(0))
None
É fácil escrever uma função que retorna uma lista de números da série de Fibonacci, ao invés de exibi-los:
1 Na verdade, passagem por referência para objeto seria uma descrição melhor, pois, se um objeto mutável for passado, quem chamou verá as
alterações feitas por quem foi chamado (por exemplo, a inclusão de itens em uma lista).
É possível definir funções com um número variável de argumentos. Existem três formas, que podem ser combinadas.
A mais útil das três é especificar um valor padrão para um ou mais argumentos. Isso cria uma função que pode ser
invocada com menos argumentos do que os que foram definidos. Por exemplo:
Os valores padrões são avaliados no momento da definição da função, e no escopo em que a função foi definida,
portanto:
i = 5
def f(arg=i):
print(arg)
i = 6
f()
irá exibir 5.
Aviso importante: Valores padrões são avaliados apenas uma vez. Isso faz diferença quando o valor é um objeto
mutável, como uma lista, dicionário, ou instâncias de classes. Por exemplo, a função a seguir acumula os argumentos
passados, nas chamadas subsequentes:
print(f(1))
print(f(2))
print(f(3))
Isso exibirá:
[1]
[1, 2]
[1, 2, 3]
Se não quiser que o valor padrão seja compartilhado entre chamadas subsequentes, pode reescrever a função assim:
Funções também podem ser chamadas usando argumentos nomeados da forma chave=valor. Por exemplo, a
função a seguir:
aceita um argumento obrigatório (voltage) e três argumentos opcionais (state, action, e type). Esta função
pode ser chamada de qualquer uma dessas formas:
Em uma chamada de função, argumentos nomeados devem vir depois dos argumentos posicionais. Todos os ar-
gumentos nomeados passados devem corresponder com argumentos aceitos pela função (ex. actor não é um
argumento nomeado válido para a função parrot), mas sua ordem é irrelevante. Isto também inclui argumentos
obrigatórios (ex.: parrot(voltage=1000) funciona). Nenhum argumento pode receber mais de um valor. Eis
um exemplo que não funciona devido a esta restrição:
Quando um último parâmetro formal no formato **nome está presente, ele recebe um dicionário (veja typesmap-
ping) contendo todos os argumentos nomeados, exceto aqueles que correspondem a um parâmetro formal. Isto pode
ser combinado com um parâmetro formal no formato *nome (descrito na próxima subseção) que recebe uma tupla
contendo os argumentos posicionais, além da lista de parâmetros formais. (*nome deve ocorrer antes de **nome.)
Por exemplo, se definirmos uma função assim:
e, claro, exibiria:
Observe que a ordem em que os argumentos nomeados são exibidos é garantida para corresponder à ordem em que
foram fornecidos na chamada da função.
Por padrão, argumentos podem ser passadas para uma função Python tanto por posição quanto explicitamente pelo
nome. Para uma melhor legibilidade e desempenho, faz sentido restringir a maneira pelo qual argumentos possam
ser passados, assim um desenvolvedor precisa apenas olhar para a definição da função para determinar se os itens são
passados por posição, por posição e nome, ou por nome.
A definição de uma função pode parecer com:
onde / e * são opcionais. Se usados, esses símbolos indicam o tipo de parâmetro pelo qual os argumentos podem ser
passados para as funções: somente-posicional, posicional-ou-nomeado, e somente-nomeado. Parâmetros nomeados
são também conhecidos como parâmetros palavra-chave.
Argumentos posicional-ou-nomeados
Se / e * não estão presentes na definição da função, argumentos podem ser passados para uma função por posição
ou por nome.
Parâmetros somente-posicionais
Olhando com um pouco mais de detalhes, é possível definir certos parâmetros como somente-posicional. Se somente-
posicional, a ordem do parâmetro importa, e os parâmetros não podem ser passados por nome. Parâmetros somente-
posicional são colocados antes de / (barra). A / é usada para logicamente separar os argumentos somente-posicional
dos demais parâmetros. Se não existe uma / na definição da função, não existe parâmetros somente-posicionais.
Parâmetros após a / podem ser posicional-ou-nomeado ou somente-nomeado.
Argumentos somente-nomeados
Para definir parâmetros como somente-nomeado, indicando que o parâmetro deve ser passado por argumento nome-
ado, colocamos um * na lista de argumentos imediatamente antes do primeiro parâmetro somente-nomeado.
Exemplos de funções
Considere o seguinte exemplo de definição de função com atenção redobrada para os marcadores / e *:
A definição da primeira função, standard_arg, a forma mais familiar, não coloca nenhuma restrição para a
chamada da função e argumentos podem ser passados por posição ou nome:
>>> standard_arg(2)
2
>>> standard_arg(arg=2)
2
A segunda função pos_only_arg está restrita ao uso de parâmetros somente posicionais, uma vez que existe uma
/ na definição da função:
>>> pos_only_arg(1)
1
>>> pos_only_arg(arg=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got an unexpected keyword argument 'arg'
A terceira função kwd_only_args permite somente argumentos nomeados como indicado pelo * na definição da
função:
>>> kwd_only_arg(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
>>> kwd_only_arg(arg=3)
3
>>> combined_example(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: combined_example() takes 2 positional arguments but 3 were given
Finalmente, considere essa definição de função que possui uma potencial colisão entre o argumento posicional name
e **kwds que possui name como uma chave:
Não é possível essa chamada devolver True, uma vez que a chave 'name' sempre será aplicada para o primeiro
parâmetro. Por exemplo:
Mas usando / (somente argumentos posicionais), isso é possível já que permite name como um argumento posicional
e 'name' como uma chave nos argumentos nomeados:
Em outras palavras, o nome de parâmetros somente-posicional podem ser usados em **kwds sem ambiguidade.
Recapitulando
Como guia:
• Use somente-posicional se você não quer que o nome do parâmetro esteja disponível para o usuário. Isso é
útil quando nomes de parâmetros não tem um significado real, se você quer forçar a ordem dos argumentos da
função quando ela é chamada ou se você precisa ter alguns parâmetros posicionais e alguns nomeados.
• Use somente-nomeado quando os nomes tem significado e a definição da função fica mais clara deixando esses
nomes explícitos ou se você quer evitar que usuários confiem na posição dos argumentos que estão sendo
passados.
• Para uma API, use somente-posicional para evitar quebras na mudança da API se os nomes dos parâmetros
forem alterados no futuro.
Finalmente, a opção menos usada é especificar que a função pode ser chamada com um número arbitrário de argu-
mentos. Esses argumentos serão empacotados em uma tupla (ver Tuplas e sequências). Antes dos argumentos em
número variável, zero ou mais argumentos normais podem estar presentes.
Normalmente, esses argumentos variádicos estarão no final da lista de parâmetros formais, porque eles englobam
todos os argumentos de entrada restantes, que são passados para a função. Quaisquer parâmetros formais que ocorrem
após o parâmetro *args são argumentos ‘somente-nomeados’ , o que significa que eles só podem ser usados como
chave-valor, em vez de argumentos posicionais:
A situação inversa ocorre quando os argumentos já estão numa lista ou tupla mas ela precisa ser explodida para
invocarmos uma função que requer argumentos posicionais separados. Por exemplo, a função range() espera
argumentos separados, start e stop. Se os valores já estiverem juntos em uma lista ou tupla, escreva a chamada de
função com o operador * para desempacotá-los da sequência:
Da mesma forma, dicionários podem produzir argumentos nomeados com o operador **:
Pequenas funções anônimas podem ser criadas com a palavra-chave lambda. Esta função retorna a soma de seus
dois argumentos: lambda a, b: a+b. As funções lambda podem ser usadas sempre que objetos função fo-
rem necessários. Eles são sintaticamente restritos a uma única expressão. Semanticamente, eles são apenas açúcar
sintático para uma definição de função normal. Como definições de funções aninhadas, as funções lambda podem
referenciar variáveis contidas no escopo:
O exemplo acima usa uma expressão lambda para retornar uma função. Outro uso é passar uma pequena função
como um argumento:
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
Aqui estão algumas convenções sobre o conteúdo e formatação de strings de documentação, também conhecidas
como docstrings.
A primeira linha deve sempre ser curta, um resumo conciso do propósito do objeto. Por brevidade, não deve expli-
citamente se referir ao nome ou tipo do objeto, uma vez que estas informações estão disponíveis por outros meios
(exceto se o nome da função for o próprio verbo que descreve a finalidade da função). Essa linha deve começar com
letra maiúscula e terminar com ponto.
Se existem mais linhas na string de documentação, a segunda linha deve estar em branco, separando visualmente o
resumo do resto da descrição. As linhas seguintes devem conter um ou mais parágrafos descrevendo as convenções
de chamada ao objeto, seus efeitos colaterais, etc.
O analisador Python não remove a indentação de literais string multilinha. Portanto, ferramentas que processem
strings de documentação precisam lidar com isso, quando desejável. Existe uma convenção para isso. A primeira
linha não vazia após a linha de sumário determina a indentação para o resto da string de documentação. (Não
podemos usar a primeira linha para isso porque ela em geral está adjacente às aspas que iniciam a string, portanto
sua indentação real não fica aparente.) Espaços em branco “equivalentes” a essa indentação são então removidos do
início das demais linhas da string. Linhas com indentação menor não devem ocorrer, mas se ocorrerem, todos os
espaços à sua esquerda são removidos. A equivalência de espaços em branco deve ser testada após a expansão das
tabulações (8 espaços, normalmente).
Eis um exemplo de uma string de documentação multilinha:
Anotações de função são informações de metadados completamente opcionais sobre os tipos usados pelas funções
definidas pelo usuário (veja PEP 3107 e PEP 484 para mais informações).
Anotações são armazenadas no atributo __annotations__ da função, como um dicionário, e não tem efeito
em nenhuma outra parte da função. Anotações nos parâmetros são definidas por um dois-pontos após o nome do
parâmetro, seguido por uma expressão que representa o valor da anotação. Anotações de retorno são definidas pelo
literal ->, seguido por uma expressão, entre a lista de parâmetros e os dois-pontos que indica o final do comando def.
O exemplo a seguir tem um argumento posicional, um argumento nomeado e o seu valor de retorno está anotado:
Agora que está prestes a escrever códigos mais longos e complexos em Python, é um bom momento para falar sobre
estilo de codificação. A maioria das linguagens podem ser escritas (ou formatadas) em diferentes estilos; alguns são
mais legíveis do que outros. Tornar o seu código mais fácil de ler, para os outros, é sempre uma boa ideia, e adotar
um estilo de codificação agradável ajuda bastante.
Em Python, a PEP 8 tornou-se o guia de estilo adotado pela maioria dos projetos; promove um estilo de codificação
muito legível e visualmente agradável. Todo desenvolvedor Python deve lê-lo em algum momento; eis os pontos mais
importantes, selecionados para você:
• Use indentação com 4 espaços, e não use tabulações.
4 espaços são um bom meio termo entre indentação estreita (permite maior profundidade de aninhamento) e
indentação larga (mais fácil de ler). Tabulações trazem complicações, e o melhor é não usar.
• Quebre as linhas de modo que não excedam 79 caracteres.
Isso ajuda os usuários com telas pequenas e torna possível abrir vários arquivos de código lado a lado em telas
maiores.
• Deixe linhas em branco para separar funções e classes, e blocos de código dentro de funções.
• Quando possível, coloque comentários em uma linha própria.
• Escreva strings de documentação.
• Use espaços ao redor de operadores e após vírgulas, mas não diretamente dentro de parênteses, colchetes e
chaves: a = f(1, 2) + g(3, 4).
• Nomeie suas classes e funções de forma consistente; a convenção é usar MaiusculoCamelCase para clas-
ses e minusculo_com_sublinhado para funções e métodos. Sempre use self como o nome para o
primeiro argumento dos métodos (veja Uma primeira olhada nas classes para mais informações sobre classes
e métodos).
• Não use codificações exóticas se o seu código é feito para ser usado em um contexto internacional. O padrão
do Python, UTF-8, ou mesmo ASCII puro funciona bem em qualquer caso.
• Da mesma forma, não use caracteres não-ASCII em identificadores se houver apenas a menor chance de pessoas
falando um idioma diferente ler ou manter o código.
Estruturas de dados
Esse capítulo descreve algumas coisas que você já aprendeu em detalhes e adiciona algumas coisas novas também.
O tipo de dado lista tem ainda mais métodos. Aqui estão apresentados todos os métodos de objetos do tipo lista:
list.append(x)
Adiciona um item ao fim da lista. Equivalente a a[len(a):] = [x].
list.extend(iterable)
Prolonga a lista, adicionando no fim todos os elementos do argumento iterable passado como parâmetro. Equi-
valente a a[len(a):] = iterable.
list.insert(i, x)
Insere um item em uma dada posição. O primeiro argumento é o índice do elemento antes do qual será feita
a inserção, assim a.insert(0, x) insere um elemento na frente da lista e a.insert(len(a), x) e
equivale a a.append(x).
list.remove(x)
Remove o primeiro item encontrado na lista cujo valor é igual a x. Se não existir valor igual, uma exceção
ValueError é levantada.
list.pop([i ])
Remove um item em uma dada posição na lista e o retorna. Se nenhum índice é especificado, a.pop()
remove e devolve o último item da lista. (Os colchetes ao redor do i na demonstração do método indica que
o parâmetro é opcional, e não que é necessário escrever estes colchetes ao chamar o método. Você verá este
tipo de notação frequentemente na Biblioteca de Referência Python.)
list.clear()
Remove todos os itens de uma lista. Equivalente a del a[:].
list.index(x[, start [, end ]])
Devolve o índice base-zero do primeiro item cujo valor é igual a x, levantando ValueError se este valor não
existe.
Os argumentos opcionais start e end são interpretados como nas notações de fatiamento e são usados para
limitar a busca para uma subsequência específica da lista. O índice retornado é calculado relativo ao começo
da sequência inteira e não referente ao argumento start.
33
Python Tutorial, Release 3.9.1
list.count(x)
Devolve o número de vezes em que x aparece na lista.
list.sort(*, key=None, reverse=False)
Ordena os itens na lista (os argumentos podem ser usados para personalizar a ordenação, veja a função
sorted() para maiores explicações).
list.reverse()
Inverte a ordem dos elementos na lista.
list.copy()
Devolve uma cópia rasa da lista. Equivalente a a[:].
Um exemplo que usa a maior parte dos métodos das listas:
Você pode ter percebido que métodos como insert, remove ou sort, que apenas modificam a lista, não têm
valor de retorno impresso – eles retornam o None padrão.1 Isto é um princípio de design para todas as estruturas de
dados mutáveis em Python.
Outra coisa que você deve estar atento é que nem todos os dados podem ser ordenados ou comparados. Por exemplo,
, [None, 'hello', 10] não podem ser ordenados, pois inteiros não podem ser comparados a strings e None
não pode ser comparado a nenhum outro tipo. Além disso, existem alguns tipos de dados que não possuem uma
relação de ordem definida. Por exemplo, 3+4j < 5+7j não é uma comparação válida.
Os métodos de lista tornam muito fácil utilizar listas como pilhas, onde o item adicionado por último é o primeiro a
ser recuperado (política “último a entrar, primeiro a sair”). Para adicionar um item ao topo da pilha, use append().
Para recuperar um item do topo da pilha use pop() sem nenhum índice. Por exemplo:
Você também pode usar uma lista como uma fila, onde o primeiro item adicionado é o primeiro a ser recuperado
(política “primeiro a entrar, primeiro a sair”); porém, listas não são eficientes para esta finalidade. Embora appends e
pops no final da lista sejam rápidos, fazer inserts ou pops no início da lista é lento (porque todos os demais elementos
têm que ser deslocados).
Para implementar uma fila, use a classe collections.deque que foi projetada para permitir appends e pops
eficientes nas duas extremidades. Por exemplo:
Compreensões de lista fornece uma maneira concisa de criar uma lista. Aplicações comuns são criar novas listas
onde cada elemento é o resultado de alguma operação aplicada a cada elemento de outra sequência ou iterável, ou
criar uma subsequência de elementos que satisfaçam uma certa condição. (N.d.T. o termo original em inglês é list
comprehensions, muito utilizado no Brasil; também se usa a abreviação listcomp).
Por exemplo, suponha que queremos criar uma lista de quadrados, assim:
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Note que isto cria (ou sobrescreve) uma variável chamada x que ainda existe após o término do laço. Podemos
calcular a lista dos quadrados sem qualquer efeito colateral usando:
contexto das cláusulas for e if. Por exemplo, essa compreensão combina os elementos de duas listas se eles forem
diferentes:
e é equivalente a:
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
A expressão inicial em uma compreensão de lista pode ser qualquer expressão arbitrária, incluindo outra compreensão
de lista.
Observe este exemplo de uma matriz 3x4 implementada como uma lista de 3 listas de comprimento 4:
>>> matrix = [
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
Como vimos na seção anterior, a compreensão de lista aninhada é computada no contexto da cláusula for seguinte,
portanto o exemplo acima equivale a:
>>> transposed = []
>>> for i in range(4):
... transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Na prática, você deve dar preferência a funções embutidas em vez de expressões complexas. A função zip() resolve
muito bem este caso de uso:
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
Veja Desempacotando listas de argumentos para entender o uso do asterisco neste exemplo.
Existe uma maneira de remover um item de uma lista usando seu índice no lugar do seu valor: a instrução del. Ele
difere do método pop() que devolve um valor. A instrução del pode também ser utilizada para remover fatias de
uma lista ou limpar a lista inteira (que fizemos antes atribuindo uma lista vazia à fatia a[:]). Por exemplo:
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
(continua na próxima página)
del também pode ser usado para remover totalmente uma variável:
>>> del a
Referenciar a variável a depois de sua remoção constitui erro (pelo menos até que seja feita uma nova atribuição para
ela). Encontraremos outros usos para a instrução del mais tarde.
Vimos que listas e strings têm muitas propriedades em comum, como indexação e operações de fatiamento. Elas são
dois exemplos de sequências (veja typesseq). Como Python é uma linguagem em evolução, outros tipos de sequências
podem ser adicionados. Existe ainda um outro tipo de sequência padrão na linguagem: a tupla.
Uma tupla consiste em uma sequência de valores separados por vírgulas, por exemplo:
>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])
Como você pode ver no trecho acima, na saída do console as tuplas são sempre envolvidas por parênteses, assim tuplas
aninhadas podem ser lidas corretamente. Na criação, tuplas podem ser envolvidas ou não por parênteses, desde que
o contexto não exija os parênteses (como no caso da tupla dentro de uma expressão maior). Não é possível atribuir
itens individuais de uma tupla, contudo é possível criar tuplas que contenham objetos mutáveis, como listas.
Apesar de tuplas serem similares a listas, elas são frequentemente utilizadas em situações diferentes e com propósitos
distintos. Tuplas são imutáveis, e usualmente contém uma sequência heterogênea de elementos que são acessados via
desempacotamento (ver a seguir nessa seção) ou índice (ou mesmo por um atributo no caso de namedtuples).
Listas são mutáveis, e seus elementos geralmente são homogêneos e são acessados iterando sobre a lista.
Um problema especial é a criação de tuplas contendo 0 ou 1 itens: a sintaxe usa certos truques para acomodar estes
casos. Tuplas vazias são construídas por um par de parênteses vazios; uma tupla unitária é construída por um único
valor e uma vírgula entre parênteses (não basta colocar um único valor entre parênteses). Feio, mas funciona. Por
exemplo:
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
(continua na próxima página)
A instrução t = 12345, 54321, 'bom dia!' é um exemplo de empacotamento de tupla: os valores 12345,
54321 e 'bom dia!' são empacotados em uma tupla. A operação inversa também é possível:
>>> x, y, z = t
Isso é chamado, apropriadamente, de sequência de desempacotamento e funciona para qualquer sequência no lado
direito. O desempacotamento de sequência requer que haja tantas variáveis no lado esquerdo do sinal de igual,
quanto existem de elementos na sequência. Observe que a atribuição múltipla é, na verdade, apenas uma combinação
de empacotamento de tupla e desempacotamento de sequência.
5.4 Conjuntos
Python também inclui um tipo de dados para conjuntos, chamado set. Um conjunto é uma coleção desordenada
de elementos, sem elementos repetidos. Usos comuns para conjuntos incluem a verificação eficiente da existência
de objetos e a eliminação de itens duplicados. Conjuntos também suportam operações matemáticas como união,
interseção, diferença e diferença simétrica.
Chaves ou a função set() podem ser usados para criar conjuntos. Note: para criar um conjunto vazio você precisa
usar set(), não {}; este último cria um dicionário vazio, uma estrutura de dados que discutiremos na próxima
seção.
Uma pequena demonstração:
Da mesma forma que compreensão de listas, compreensões de conjunto também são suportadas:
5.4. Conjuntos 39
Python Tutorial, Release 3.9.1
5.5 Dicionários
Outra estrutura de dados muito útil embutida em Python é o dicionário, cujo tipo é dict (ver typesmapping).
Dicionários são também chamados de “memória associativa” ou “vetor associativo” em outras linguagens. Diferente
de sequências que são indexadas por inteiros, dicionários são indexados por chaves (keys), que podem ser de qualquer
tipo imutável (como strings e inteiros). Tuplas também podem ser chaves se contiverem apenas strings, inteiros ou
outras tuplas. Se a tupla contiver, direta ou indiretamente, qualquer valor mutável, não poderá ser chave. Listas não
podem ser usadas como chaves porque podem ser modificadas internamente pela atribuição em índices ou fatias, e
por métodos como append() e extend().
Um bom modelo mental é imaginar um dicionário como um conjunto não-ordenado de pares chave:valor, onde as
chaves são únicas em uma dada instância do dicionário. Dicionários são delimitados por chaves: {}, e contém uma
lista de pares chave:valor separada por vírgulas. Dessa forma também será exibido o conteúdo de um dicionário no
console do Python. O dicionário vazio é {}.
As principais operações em um dicionário são armazenar e recuperar valores a partir de chaves. Também é possível
remover um par chave:valor com o comando del. Se você armazenar um valor utilizando uma chave já presente, o
antigo valor será substituído pelo novo. Se tentar recuperar um valor usando uma chave inexistente, será gerado um
erro.
Executar list(d) em um dicionário devolve a lista de todas as chaves presentes no dicionário, na ordem de inserção
(se desejar ordená-las basta usar a função sorted(d)). Para verificar a existência de uma chave, use o operador
in.
A seguir, um exemplo de uso do dicionário:
Além disso, as compreensões de dicionários podem ser usadas para criar dicionários a partir de expressões arbitrárias
de chave e valor:
Quando chaves são strings simples, é mais fácil especificar os pares usando argumentos nomeados no construtor:
Ao iterar sobre dicionários, a chave e o valor correspondente podem ser obtidos simultaneamente usando o método
items().
Ao iterar sobre sequências, a posição e o valor correspondente podem ser obtidos simultaneamente usando a função
enumerate().
Para percorrer duas ou mais sequências ao mesmo tempo, as entradas podem ser pareadas com a função zip().
Para percorrer uma sequência em ordem inversa, chame a função reversed() com a sequência na ordem original.
Para percorrer uma sequência de maneira ordenada, use a função sorted(), que retorna uma lista ordenada com
os itens, mantendo a sequência original inalterada.
Usar set() em uma sequência elimina elementos duplicados. O uso de sorted() em combinação com set()
sobre uma sequência é uma maneira idiomática de fazer um loop sobre elementos exclusivos da sequência na ordem
de classificação.
Às vezes é tentador alterar uma lista enquanto você itera sobre ela; porém, costuma ser mais simples e seguro criar
uma nova lista.
As condições de controle usadas em while e if podem conter quaisquer operadores, não apenas comparações.
Os operadores de comparação in e not in verificam se um valor ocorre (ou não ocorre) em uma dada sequência.
Os operadores is e is not comparam se dois objetos são na verdade o mesmo objeto; isto só é relevante no
contexto de objetos mutáveis, como listas. Todos os operadores de comparação possuem a mesma precedência, que
é menor do que a prioridade de todos os operadores numéricos.
Comparações podem ser encadeadas: Por exemplo a < b == c testa se a é menor que b e também se b é igual
a c.
Comparações podem ser combinadas através de operadores booleanos and e or, e o resultado de uma comparação
(ou de qualquer outra expressão), pode ter seu valor booleano negado através de not. Estes possuem menor priori-
dade que os demais operadores de comparação. Entre eles, not é o de maior prioridade e or o de menor. Dessa
forma, a condição A and not B or C é equivalente a (A and (not B)) or C. Naturalmente, parênteses
podem ser usados para expressar o agrupamento desejado.
Os operadores booleanos and e or são operadores curto-circuito: seus argumentos são avaliados da esquerda para a
direita, e a avaliação encerra quando o resultado é determinado. Por exemplo, se A e C são expressões verdadeiras,
mas B é falsa, então A and B and C não chega a avaliar a expressão C. Em geral, quando usado sobre valores
genéricos e não como booleanos, o valor do resultado de um operador curto-circuito é o último valor avaliado na
expressão.
É possível atribuir o resultado de uma comparação ou outra expressão booleana para uma variável. Por exemplo:
Observe que no Python, ao contrário de C, a atribuição dentro de expressões deve ser feita explicitamente com o
operador morsa :=. Isso evita uma classe comum de problemas encontrados nos programas C: digitar = em uma
expressão quando == era o planejado.
Objetos sequência podem ser comparados com outros objetos sequência, desde que o tipo das sequências seja o
mesmo. A comparação utiliza a ordem lexicográfica: primeiramente os dois primeiros itens são comparados, e se
diferirem isto determinará o resultado da comparação, caso contrário os próximos dois itens serão comparados, e
assim por diante até que se tenha exaurido alguma das sequências. Se em uma comparação de itens, os mesmos
forem também sequências (aninhadas), então é disparada recursivamente outra comparação lexicográfica. Se todos
os itens da sequência forem iguais, então as sequências são ditas iguais. Se uma das sequências é uma subsequência
da outra, então a subsequência é a menor. A comparação lexicográfica de strings utiliza codificação Unicode para
definir a ordenação. Alguns exemplos de comparações entre sequências do mesmo tipo:
Note que comparar objetos de tipos diferentes com < ou > é permitido desde que os objetos possuam os métodos de
comparação apropriados. Por exemplo, tipos numéricos mistos são comparados de acordo com os seus valores numé-
ricos, portanto 0 é igual a 0.0, etc. Em caso contrário, ao invés de fornecer uma ordenação arbitrária, o interpretador
levantará um TypeError.
Módulos
Ao sair e entrar de novo no interpretador Python, as definições anteriores (funções e variáveis) são perdidas. Portanto,
se quiser escrever um programa maior, será mais eficiente usar um editor de texto para preparar as entradas para o
interpretador, e executá-lo usando o arquivo como entrada. Isso é conhecido como criar um script. Se o programa
se torna ainda maior, é uma boa prática dividi-lo em arquivos menores, para facilitar a manutenção. Também é
preferível usar um arquivo separado para uma função que você escreveria em vários programas diferentes, para não
copiar a definição de função em cada um deles.
Para permitir isso, o Python tem uma maneira de colocar as definições em um arquivo e então usá-las em um script
ou em uma execução interativa do interpretador. Tal arquivo é chamado de módulo; definições de um módulo podem
ser importadas para outros módulos, ou para o módulo principal (a coleção de variáveis a que você tem acesso num
script executado como um programa e no modo calculadora).
Um módulo é um arquivo contendo definições e instruções Python. O nome do arquivo é o nome do módulo acrescido
do sufixo .py. Dentro de um módulo, o nome do módulo (como uma string) está disponível como o valor da variável
global __name__. Por exemplo, use seu editor de texto favorito para criar um arquivo chamado fibo.py no
diretório atual com o seguinte conteúdo:
45
Python Tutorial, Release 3.9.1
Isso não coloca os nomes das funções definidas em fibo diretamente na tabela de símbolos atual; isso coloca somente
o nome do módulo fibo. Usando o nome do módulo você pode acessar as funções:
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
Se pretender usar uma função muitas vezes, você pode atribui-lá a um nome local:
Um módulo pode conter tanto instruções executáveis quanto definições de funções e classes. Essas instruções servem
para inicializar o módulo. Eles são executados somente na primeira vez que o módulo é encontrado em uma instrução
de importação.1 (Também rodam se o arquivo é executado como um script.)
Cada módulo tem sua própria tabela de símbolos privada, que é usada como tabela de símbolos global para todas
as funções definidas no módulo. Assim, o autor de um módulo pode usar variáveis globais no seu módulo sem
se preocupar com conflitos acidentais com as variáveis globais do usuário. Por outro lado, se você precisar usar
uma variável global de um módulo, poderá fazê-lo com a mesma notação usada para se referir às suas funções,
nomemodulo.nomeitem.
Módulos podem importar outros módulos. É costume, porém não obrigatório, colocar todos os comandos import
no início do módulo (ou script , se preferir). As definições do módulo importado são colocadas na tabela de símbolos
global do módulo que faz a importação.
Existe uma variante do comando import que importa definições de um módulo diretamente para a tabela de sím-
bolos do módulo importador. Por exemplo:
Isso não coloca o nome do módulo de onde foram feitas as importações na tabela de símbolos local (assim, no exemplo,
fibo não está definido).
Existe ainda uma variante que importa todos os nomes definidos em um módulo:
Isso importa todos as declarações de nomes, exceto aqueles que iniciam com um sublinhado (_). Na maioria dos
casos, programadores Python não usam esta facilidade porque ela introduz um conjunto desconhecido de nomes no
ambiente, podendo esconder outros nomes previamente definidos.
Note que, em geral, a prática do import * de um módulo ou pacote é desaprovada, uma vez que muitas vezes
dificulta a leitura do código. Contudo, é aceitável para diminuir a digitação em sessões interativas.
Se o nome do módulo é seguido pela palavra-chave as, o nome a seguir é vinculado diretamente ao módulo importado.
1 [#] Na verdade, definições de funções também são ‘instruções’ que são ‘executados’; a execução da definição de uma função coloca o nome
46 Capítulo 6. Módulos
Python Tutorial, Release 3.9.1
Isto efetivamente importa o módulo, da mesma maneira que import fibo fará, com a única diferença de estar
disponível com o nome fib.
Também pode ser utilizado com a palavra-chave from, com efeitos similares:
Nota: For efficiency reasons, each module is only imported once per interpreter session. Therefore, if you
change your modules, you must restart the interpreter – or, if it’s just one module you want to test interactively,
use importlib.reload(), e.g. import importlib; importlib.reload(modulename).
o código no módulo será executado, da mesma forma que quando é importado, mas com a variável __name__ com
valor "__main__". Isto significa que adicionando este código ao final do seu módulo:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
você pode tornar o arquivo utilizável tanto como script quanto como um módulo importável, porque o código que
analisa a linha de comando só roda se o módulo é executado como arquivo “principal”:
$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
Isso é frequentemente usado para fornecer uma interface de usuário conveniente para um módulo, ou para realizar
testes (rodando o módulo como um script executa um conjunto de testes).
Quando um módulo chamado spam é importado, o interpretador procura um módulo embutido com este nome. Se
não encontra, procura um arquivo chamado spam.py em uma lista de diretórios incluídos na variável sys.path.
A sys.path é inicializada com estes locais:
• O diretório que contém o script importador (ou o diretório atual quando nenhum arquivo é especificado).
• A variável de ambiente PYTHONPATH (uma lista de nomes de diretórios, com a mesma sintaxe da variável de
ambiente PATH).
• Padrões dependentes da instalação.
Nota: Nos sistemas de arquivos que suportam links simbólicos, o diretório contendo o script de entrada é resul-
tante do diretório apontado pelo link simbólico. Em outras palavras o diretório que contém o link simbólico não é
adicionado ao caminho de busca de módulos.
Após a inicialização, programas Python podem modificar sys.path. O diretório que contém o script sendo execu-
tado é colocado no início da lista de caminhos, à frente do caminho da biblioteca padrão. Isto significa que módulos
nesse diretório serão carregados, no lugar de módulos com o mesmo nome na biblioteca padrão. Isso costuma ser
um erro, a menos que seja intencional. Veja a seção Módulos padrões para mais informações.
Para acelerar o carregamento de módulos, o Python guarda versões compiladas de cada módulo no diretório
__pycache__ com o nome modulo.versão.pyc, onde a versão corresponde ao formato do arquivo com-
pilado; geralmente contêm o número da versão Python utilizada. Por exemplo, no CPython release 3.3 a versão
compilada de spam.py será guardada como __pycache__/spam.cpython-33.pyc. Esta convenção de no-
mes permite a coexistência de módulos compilados de diferentes releases e versões de Python.
O Python verifica a data de modificação do arquivo fonte mediante a versão compilada, para ver se está desatualizada
e precisa ser recompilada. É um processo completamente automático. Além disso, os módulos compilados são
independentes de plataforma, portanto a mesma biblioteca pode ser compartilhada entre sistemas de arquiteturas
diferentes.
O Python não verifica as versões compiladas em duas circunstâncias. Primeiro, sempre recompila e não armazena o
resultado para módulos carregados diretamente da linha de comando. Segundo, não verifica se não houver um módulo
fonte. Para suportar uma distribuição sem fontes (somente as versões compiladas), o módulo compilado deve estar
no diretório de fontes, e não deve haver um módulo fonte.
Algumas dicas para especialistas:
• Você pode usar as opções -O ou -OO no comando Python para reduzir o tamanho de um módulo compilado.
A opção -O remove comandos assert, e a opção -OO remove, além dos comandos assert, as strings de do-
cumentações. Como alguns programas podem contar com essa disponibilidade, só use essa opção se souber
o que está fazendo. Módulos “otimizados” tem uma marcação opt- e são geralmente de menor tamanho.
Futuros releases podem mudar os efeitos da otimização.
• Um programa não roda mais rápido quando é lido de um arquivo .pyc do que quando lido de um arquivo
.py; a única coisa que é mais rápida com arquivos .pyc é sua velocidade de carregamento.
• O módulo compileall pode criar arquivos .pyc para todos os módulos de um diretório.
• Há mais detalhes desse processo, incluindo um fluxograma de decisões, no PEP 3147.
O Python traz uma biblioteca padrão de módulos, descrita em um documento em separado, a Referência da Biblioteca
Python (doravante “Referência da Biblioteca”). Alguns módulos estão embutidos no interpretador; estes possibilitam
acesso a operações que não são parte do núcleo da linguagem, mas estão no interpretador seja por eficiência ou para
permitir o acesso a chamadas do sistema operacional. O conjunto destes módulos é uma opção de configuração que
depende também da plataforma utilizada. Por exemplo, o módulo winreg só está disponível em sistemas Windows.
Existe um módulo que requer especial atenção: sys, que é embutido em qualquer interpretador Python. As variáveis
sys.ps1 e sys.ps2 definem as strings utilizadas como prompt primário e secundário:
48 Capítulo 6. Módulos
Python Tutorial, Release 3.9.1
A função embutida dir() é usada para descobrir quais nomes são definidos por um módulo. Ela devolve uma lista
ordenada de strings:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
Observe que ela lista todo tipo de nomes: variáveis, módulos, funções, etc.
dir() não lista os nomes de variáveis e funções embutidas. Esta lista está disponível no módulo padrão builtins:
6.4 Pacotes
Os pacotes são uma maneira de estruturar o “espaço de nomes” dos módulos Python, usando “nomes de módulo com
pontos”. Por exemplo, o nome do módulo A.B designa um submódulo chamado B, em um pacote chamado A. Assim
como o uso de módulos evita que os autores de módulos diferentes tenham que se preocupar com nomes de variáveis
globais, o uso de nomes de módulos com pontos evita que os autores de pacotes com muitos módulos, como NumPy
ou Pillow, tenham que se preocupar com os nomes dos módulos uns dos outros.
Suponha que você queira projetar uma coleção de módulos (um “pacote”) para o gerenciamento uniforme de arquivos
de som. Existem muitos formatos diferentes (normalmente identificados pela extensão do nome de arquivo, por
exemplo .wav, .aiff, .au), de forma que você pode precisar criar e manter uma crescente coleção de módulos de
conversão entre formatos. Ainda podem existir muitas operações diferentes, passíveis de aplicação sobre os arquivos
de som (mixagem, eco, equalização, efeito stereo artificial). Logo, possivelmente você também estará escrevendo
uma coleção sempre crescente de módulos para aplicar estas operações. Eis uma possível estrutura para o seu pacote
(expressa em termos de um sistema de arquivos hierárquico):
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
(continua na próxima página)
50 Capítulo 6. Módulos
Python Tutorial, Release 3.9.1
Ao importar esse pacote, Python busca pelo subdiretório com mesmo nome, nos diretórios listados em sys.path.
Os arquivos __init__.py são necessários para que o Python trate diretórios contendo o arquivo como pacotes.
Isso previne que diretórios com um nome comum, como string, ocultem, involuntariamente, módulos válidos que
ocorrem posteriormente no caminho de busca do módulo. No caso mais simples, __init__.py pode ser apenas
um arquivo vazio, mas pode também executar código de inicialização do pacote, ou configurar a variável __all__,
descrita mais adiante.
Usuários do pacote podem importar módulos individuais, por exemplo:
import sound.effects.echo
Isso carrega o submódulo sound.effects.echo. Ele deve ser referenciado com seu nome completo, como em:
Isso carrega o submódulo echo sem necessidade de mencionar o prefixo do pacote no momento da utilização, assim:
Novamente, isso carrega o submódulo echo, mas a função echofilter() está acessível diretamente sem prefixo:
Observe que ao utilizar from pacote import item, o item pode ser um subpacote, submódulo, classe, função
ou variável. O comando import primeiro testa se o item está definido no pacote, senão assume que é um módulo e
tenta carregá-lo. Se falhar em encontrar o módulo, uma exceção ImportError é levantada.
Em oposição, em uma construção como import item.subitem.subsubitem, cada item, com exceção do
último, deve ser um pacote. O último pode ser também um pacote ou módulo, mas nunca uma classe, função ou
variável contida em um módulo.
6.4. Pacotes 51
Python Tutorial, Release 3.9.1
Agora, o que acontece quando um usuário escreve from sound.effects import * ? Idealmente, poderia
se esperar que este comando vasculhasse o sistema de arquivos, encontrasse todos os submódulos presentes no pacote,
e os importasse. Isso poderia demorar muito e a importação de submódulos pode ocasionar efeitos colaterais, que
somente deveriam ocorrer quando o submódulo é explicitamente importado.
A única solução é o autor do pacote fornecer um índice explícito do pacote. O comando import usa a seguinte
convenção: se o arquivo __init__.py do pacote define uma lista chamada __all__, então esta lista indica
os nomes dos módulos a serem importados quando o comando from pacote import * é acionado. Fica a
cargo do autor do pacote manter esta lista atualizada, inclusive fica a seu critério excluir inteiramente o suporte a
importação direta de todo o pacote através de from pacote import *. Por exemplo, o arquivo sounds/
effects/__init__.py poderia conter apenas:
Isso significaria que from sound.effects import * importaria apenas os três submódulos especificados no
pacote sound.
Se __all__ não estiver definido, o comando from sound.effects import * não importa todos os submó-
dulos do pacote sound.effects no espaço de nomes atual. Há apenas garantia que o pacote sound.effects
foi importado (possivelmente executando qualquer código de inicialização em __init__.py) juntamente com os
nomes definidos no pacote. Isso inclui todo nome definido em __init__.py bem como em qualquer submódulo
importado a partir deste. Também inclui quaisquer submódulos do pacote que tenham sido carregados explicitamente
por comandos import anteriores. Considere o código abaixo:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
Nesse exemplo, os nomes echo e surround são importados no espaço de nomes atual, no momento em que o co-
mando from...import é executado, pois estão definidos no pacote sound.effects. (Isso também funciona
quando __all__ estiver definida.)
Apesar de que certos módulos são projetados para exportar apenas nomes conforme algum critério quando se faz
import *, ainda assim essa sintaxe é considerada uma prática ruim em código de produção.
Lembre-se, não há nada errado em usar from pacote import submodulo_especifico! De fato, essa
é a notação recomendada, a menos que o módulo importado necessite usar submódulos com o mesmo nome, de
diferentes pacotes.
Quando pacotes são estruturados em subpacotes (como no pacote sound do exemplo), pode-se usar a sintaxe de
importações absolutas para se referir aos submódulos de pacotes irmãos (o que na prática é uma forma de fazer
um import relativo, a partir da base do pacote). Por exemplo, se o módulo sound.filters.vocoder precisa
usar o módulo echo do pacote sound.effects, é preciso importá-lo com from sound.effects import
echo.
Também é possível escrever imports relativos, com a forma from modulo import nome. Esses imports usam
pontos para indicar o pacote pai e o atual, envolvidos no import relativo. Do módulo surround, por exemplo,
pode-se usar:
Note que imports relativos são baseados no nome do módulo atual. Uma vez que o nome do módulo principal é
sempre "__main__", módulos destinados ao uso como módulo principal de um aplicativo Python devem sempre
usar imports absolutos.
52 Capítulo 6. Módulos
Python Tutorial, Release 3.9.1
Pacotes possuem mais um atributo especial, __path__. Inicializado como uma lista contendo o nome do diretório
onde está o arquivo __init__.py do pacote, antes do código naquele arquivo ser executado. Esta variável pode
ser modificada; isso afeta a busca futura de módulos e subpacotes contidos no pacote.
Apesar de não ser muito usado, esse mecanismo permite estender o conjunto de módulos encontrados em um pacote.
6.4. Pacotes 53
Python Tutorial, Release 3.9.1
54 Capítulo 6. Módulos
CAPÍTULO 7
Entrada e saída
Existem várias maneiras de apresentar a saída de um programa; os dados podem ser exibidos em forma legível para
seres humanos, ou escritos em arquivos para uso posterior. Este capítulo apresentará algumas das possibilidades.
Até agora vimos duas maneiras de exibir valores: expressões e a função print(). (Uma outra maneira é utilizar o
método write() de objetos do tipo arquivo; o arquivo saída padrão pode ser referenciado como sys.stdout.
Veja a Referência da Biblioteca Python para mais informações sobre isso.)
Muitas vezes se deseja mais controle sobre a formatação da saída do que simplesmente exibir valores separados por
espaço. Existem várias maneiras de formatar a saída.
• Para usar strings literais formatadas, comece uma string com f ou F, antes de abrir as aspas ou aspas triplas.
Dentro dessa string, pode-se escrever uma expressão Python entre caracteres { e }, que podem se referir a
variáveis, ou valores literais.
• O método de strings str.format() requer mais esforço manual. Ainda será necessário usar { e } para
marcar onde a variável será substituída e pode-se incluir diretivas de formatação detalhadas, mas também
precisará incluir a informação a ser formatada.
• Finalmente, pode-se fazer todo o tratamento da saída usando as operações de fatiamento e concatenação de
strings para criar qualquer layout que se possa imaginar. O tipo string possui alguns métodos que realizam
operações úteis para preenchimento de strings para uma determinada largura de coluna.
Quando não é necessário sofisticar a saída, mas apenas exibir algumas variáveis com propósito de depuração, pode-se
converter qualquer valor para uma string com as funções repr() ou str().
55
Python Tutorial, Release 3.9.1
A função str() serve para retornar representações de valores que sejam legíveis para as pessoas, enquanto repr()
é para gerar representações que o interpretador Python consegue ler (ou levantará uma exceção SyntaxError,
se não houver sintaxe equivalente). Para objetos que não têm uma representação adequada para consumo humano,
str() devolve o mesmo valor que repr(). Muitos valores, tal como números ou estruturas, como listas e dicio-
nários, têm a mesma representação usando quaisquer das funções. Strings, em particular, têm duas representações
distintas.
Alguns exemplos:
O módulo string contém uma classe Template que oferece ainda outra maneira de substituir valores em strings,
usando espaços reservados como $x e substituindo-os por valores de um dicionário, mas oferece muito menos controle
da formatação.
Strings literais formatadas (também chamadas f-strings, para abreviar) permite que se inclua o valor de expressões
Python dentro de uma string, prefixando-a com f ou F e escrevendo expressões na forma {expression}.
Um especificador opcional de formato pode ser incluído após a expressão. Isso permite maior controle sobre como
o valor é formatado. O exemplo a seguir arredonda pi para três casas decimais:
Passando um inteiro após o ':' fará com que o campo tenha um número mínimo de caracteres de largura. Isso é
útil para alinhar colunas.
Outros modificadores podem ser usados para converter o valor antes de ser formatado. '!a' aplica a função
ascii(), '!s' aplica a função str() e '!r' aplica a função repr()
Para uma referência dessas especificações de formatos, veja o guia de referência para formatspec.
As chaves e seus conteúdos (chamados campos de formatação) são substituídos pelos objetos passados para o método
str.format(). Um número nas chaves pode ser usado para referenciar a posição do objeto passado no método
str.format().
Se argumentos nomeados são passados para o método str.format(), seus valores serão referenciados usando o
nome do argumento:
Se uma string de formatação é muito longa, e não se deseja quebrá-la, pode ser bom fazer referência aos valores a
serem formatados por nome, em vez de posição. Isto pode ser feito passando um dicionário usando colchetes '[]'
para acessar as chaves.
Isto também pode ser feito passando o dicionário como argumento do método, usando a notação **:
Isto é particularmente útil em conjunto com a função embutida vars(), que devolve um dicionário contendo todas
as variáveis locais.
Como exemplo, as linhas seguintes produzem um conjunto de colunas alinhadas, com alguns inteiros e seus quadrados
e cubos:
Para uma visão completa da formatação de strings com str.format(), veja a seção formatstrings.
(Note que o espaço entre cada coluna foi adicionado pela forma que a função print() funciona: sempre adiciona
espaços entre seus argumentos.)
O método str.rjust() justifica uma string à direita, num campo de tamanho definido, acrescentando espaços à
esquerda. De forma similar, os métodos str.ljust(), justifica à esquerda, e str.center(), para centralizar.
Esses métodos não escrevem nada, apenas retornam uma nova string. Se a string de entrada é muito longa, os
métodos não truncarão a saída, e retornarão a mesma string, sem mudança; isso vai atrapalhar o layout da coluna,
mas geralmente é melhor do que a alternativa, que estaria distorcendo o valor. (Se realmente quiser truncar, sempre
se pode adicionar uma operação de fatiamento, como em x.ljust(n)[:n].)
Existe ainda o método str.zfill() que preenche uma string numérica com zeros à esquerda, e sabe lidar com
sinais positivos e negativos:
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
O operador % (módulo) também pode ser usado para formatação de string. Dado 'string' % valores, as
instâncias de % em string são substituídas por zero ou mais elementos de valores. Essa operação é conhecida
como interpolação de string. Por exemplo:
A função open() devolve um objeto arquivo, e é frequentemente usada com dois argumentos:
open(nome_do_arquivo, modo).
O primeiro argumento é uma string contendo o nome do arquivo. O segundo argumento é outra string, contendo
alguns caracteres que descrevem o modo como o arquivo será usado. modo pode ser 'r' quando o arquivo será
apenas lido, 'w' para escrever (se o arquivo já existir seu conteúdo prévio será apagado), e 'a' para abrir o arquivo
para adição; qualquer escrita será adicionada ao final do arquivo. A opção 'r+' abre o arquivo tanto para leitura
como para escrita. O argumento modo é opcional, em caso de omissão será assumido 'r'.
Normalmente, arquivos são abertos em modo texto, ou seja, você lê e grava strings, de e para o arquivo, numa codi-
ficação específica. Se a codificação não for especificada, o padrão é dependente da plataforma/sistema operacional
(consulte open()). Incluir 'b' ao modo abre o arquivo em modo binário: os dados são lidos e escritos na forma
de bytes. Esse modo deve ser usado para todos os arquivos que não contenham texto.
Em modo texto, o padrão durante a leitura é converter terminadores de linha específicos da plataforma (\n no Unix, \
r\n no Windows) para apenas \n. Ao escrever no modo de texto, o padrão é converter as ocorrências de \n de volta
para os finais de linha específicos da plataforma. Essa modificação de bastidores nos dados do arquivo é adequada
para arquivos de texto, mas corromperá dados binários, como arquivos JPEG ou EXE. Tenha muito cuidado para só
usar o modo binário, ao ler e gravar esses arquivos.
É uma boa prática usar a palavra-chave with ao lidar com arquivos. A vantagem é que o arquivo é fechado corre-
tamente após o término de sua utilização, mesmo que uma exceção seja levantada em algum momento. Usar with
também é muito mais curto que escrever seu bloco equivalente try-finally:
>>> # We can check that the file has been automatically closed.
>>> f.closed
True
Se você não está usando a palavra reservada with, então você deveria chamar f.close() para fechar o arquivo
e imediatamente liberar qualquer recurso do sistema usado por ele.
Aviso: Chamar f.write() sem usar a palavra reservada with ou chamar“f.close()“ pode resultar nos argu-
mentos de f.write() não serem completamente escritos no disco, mesmo se o programa for encerrado com
êxito.
Depois que um arquivo é fechado, seja por uma instrução with ou chamando f.close(), as tentativas de usar o
arquivo falharão automaticamente.
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.
Para simplificar, o resto dos exemplos nesta seção assumem que um objeto arquivo chamado f já foi criado.
Para ler o conteúdo de um arquivo, chame f.read(tamanho), que lê um punhado de dados devolvendo-os como
uma string (em modo texto) ou bytes (em modo binário). tamanho é um argumento numérico opcional. Quando
tamanho é omitido ou negativo, todo o conteúdo do arquivo é lido e devolvido; se o arquivo é duas vezes maior que
memória da máquina, o problema é seu. Caso contrário, no máximo tamanho caracteres (em modo texto) ou tamanho
bytes (em modo binário) são lidos e devolvidos. Se o fim do arquivo for atingido, f.read() devolve uma string
vazia ('').
>>> f.read()
'This is the entire file.\n'
>>> f.read()
''
O método f.readline() lê uma única linha do arquivo; o caractere de quebra de linha (\n) é mantido ao final da
string, e só é omitido na última linha do arquivo, se o arquivo não terminar com uma quebra de linha. Isso elimina a
ambiguidade do valor retornado; se f.readline() retorna uma string vazia, o fim do arquivo foi atingido. Linhas
em branco são representadas por um '\n' – uma string contendo apenas o caractere terminador de linha.
>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''
Uma maneira alternativa de ler linhas do arquivo é iterar diretamente pelo objeto arquivo. É eficiente, rápido e resulta
em código mais simples:
Se desejar ler todas as linhas de um arquivo em uma lista, pode-se usar list(f) ou f.readlines().
f.write(string) escreve o conteúdo de string para o arquivo, retornando o número de caracteres escritos.
Outros tipos de objetos precisam ser convertidos – seja para uma string (em modo texto) ou para bytes (em modo
binário) – antes de escrevê-los:
f.tell() retorna um inteiro dando a posição atual do objeto arquivo, no arquivo representado, como número de
bytes desde o início do arquivo, no modo binário, e um número ininteligível, quando no modo de texto.
Para mudar a posição, use f.seek(offset, de_onde). A nova posição é computada pela soma do desloca-
mento offset a um ponto de referência especificado pelo argumento de-onde. Se o valor de de_onde é 0,a referência
é o início do arquivo, 1 refere-se à posição atual, e 2 refere-se ao fim do arquivo. Este argumento pode ser omitido e
o valor padrão é 0, usando o início do arquivo como referência.
Em arquivos texto (abertos sem um b, em modo string), somente seeks relativos ao início do arquivo serão permitidos
(exceto se for indicado o final do arquivo, com seek(0, 2)) e o único valor válido para offset são aqueles retornados
por chamada à f.tell(), ou zero. Qualquer outro valor para offset produz um comportamento indefinido.
Objetos arquivo tem alguns método adicionais, como isatty() e truncate() que não são usados com frequên-
cia; consulte a Biblioteca de Referência para um guia completo de objetos arquivo.
Strings podem ser facilmente gravadas e lidas em um arquivo. Números dão um pouco mais de trabalho, já que o
método read() só retorna strings, que terão que ser passadas para uma função como int(), que pega uma string
como '123' e retorna seu valor numérico 123. Quando você deseja salvar tipos de dados mais complexos, como
listas e dicionários aninhados, a análise e serialização manual tornam-se complicadas.
Ao invés de ter usuários constantemente escrevendo e depurando código para gravar tipos complicados de dados
em arquivos, o Python permite que se use o popular formato de troca de dados chamado JSON (JavaScript Object
Notation). O módulo padrão chamado json pode pegar hierarquias de dados em Python e convertê-las em repre-
sentações de strings; esse processo é chamado serialização. Reconstruir os dados estruturados da representação string
é chamado desserialização. Entre serializar e desserializar, a string que representa o objeto pode ser armazenada em
um arquivo, ou estrutura de dados, ou enviada por uma conexão de rede para alguma outra máquina.
Nota: O formato JSON é comumente usado por aplicativos modernos para permitir troca de dados. Pessoas que
programam já estão familiarizadas com esse formato, o que o torna uma boa opção para interoperabilidade.
Um objeto x, pode ser visualizado na sua representação JSON com uma simples linha de código:
Outra variação da função dumps(), chamada dump(), serializa o objeto para um arquivo texto. Se f é um arquivo
texto aberto para escrita, podemos fazer isto:
json.dump(x, f)
Para decodificar o objeto novamente, se f é um objeto arquivo texto que foi aberto para leitura:
x = json.load(f)
Essa técnica de serialização simples pode manipular listas e dicionários, mas a serialização de instâncias de classes
arbitrárias no JSON requer um pouco mais de esforço. A referência para o módulo json contém uma explicação
disso.
Ver também:
O módulo pickle
Ao contrário do JSON, pickle é um protocolo que permite a serialização de objetos Python arbitrariamente complexos.
Por isso, é específico do Python e não pode ser usado para se comunicar com aplicativos escritos em outros linguagens.
Também é inseguro por padrão: desserializar dados de pickle, provenientes de uma fonte não confiável, pode executar
código arbitrário, se os dados foram criados por um invasor habilidoso.
Erros e exceções
Até agora mensagens de erro foram apenas mencionadas, mas se você testou os exemplos, talvez tenha esbarrado em
algumas. Existem pelo menos dois tipos distintos de erros: erros de sintaxe e exceções.
Erros de sintaxe, também conhecidos como erros de parse, são provavelmente os mais frequentes entre aqueles que
ainda estão aprendendo Python:
O parser repete a linha inválida e apresenta uma pequena ‘seta’ apontando para o ponto da linha em que o erro
foi detectado. O erro é causado (ou ao menos detectado) pelo símbolo que precede a seta: no exemplo, o erro foi
detectado na função print(), uma vez que um dois-pontos (':') está faltando antes dela. O nome de arquivo e
número de linha são exibidos para que você possa rastrear o erro no texto do script.
8.2 Exceções
Mesmo que um comando ou expressão estejam sintaticamente corretos, talvez ocorra um erro na hora de sua execução.
Erros detectados durante a execução são chamados exceções e não são necessariamente fatais: logo veremos como
tratá-las em programas Python. A maioria das exceções não são tratadas pelos programas e acabam resultando em
mensagens de erro:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
(continua na próxima página)
63
Python Tutorial, Release 3.9.1
A última linha da mensagem de erro indica o que aconteceu. Exceções surgem com diferentes tipos, e o tipo é exibido
como parte da mensagem: os tipos no exemplo são ZeroDivisionError, NameError e TypeError. A
string exibida como sendo o tipo da exceção é o nome da exceção embutida que ocorreu. Isso é verdade para todas
exceções pré-definidas em Python, mas não é necessariamente verdade para exceções definidas pelo usuário (embora
seja uma convenção útil). Os nomes das exceções padrões são identificadores embutidos (não palavras reservadas).
O resto da linha é um detalhamento que depende do tipo da exceção ocorrida e sua causa.
A parte anterior da mensagem de erro apresenta o contexto onde ocorreu a exceção. Essa informação é denominada
stack traceback (situação da pilha de execução). Em geral, contém uma lista de linhas do código-fonte, sem apresentar,
no entanto, linhas lidas da entrada padrão.
bltin-exceptions lista as exceções pré-definidas e seus significados.
É possível escrever programas que tratam exceções específicas. Observe o exemplo seguinte, que pede dados ao
usuário até que um inteiro válido seja fornecido, ainda permitindo que o programa seja interrompido (utilizando
Control-C ou seja lá o que for que o sistema operacional suporte); note que uma interrupção gerada pelo usuário
será sinalizada pela exceção KeyboardInterrupt.
>>> while True:
... try:
... x = int(input("Please enter a number: "))
... break
... except ValueError:
... print("Oops! That was no valid number. Try again...")
...
Uma classe em uma cláusula except é compatível com uma exceção se ela é da mesma classe ou de uma classe
base desta (mas o contrário não é válido — uma cláusula de exceção listando uma classe derivada não é compatível
com uma classe base). Por exemplo, o seguinte código irá mostrar B, C, D nesta ordem:
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
Se a ordem das cláusulas fosse invertida (except B no início), seria exibido B, B, B — somente a primeira cláusula
de exceção compatível é ativada.
A última cláusula de exceção pode omitir o nome da exceção, funcionando como um curinga. Utilize esse recurso
com extrema cautela, uma vez que isso pode esconder erros do programador e do usuário! Também pode ser utilizado
para exibir uma mensagem de erro e então levantar novamente a exceção (permitindo que o invocador da função atual
também possa tratá-la):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
A construção try … except possui uma cláusula else opcional, que quando presente, deve ser colocada depois de
todas as outras cláusulas. É útil para um código que precisa ser executado se nenhuma exceção foi levantada. Por
exemplo:
É melhor usar a cláusula else do que adicionar código adicional à cláusula try porque ela evita que acidentalmente
seja tratada uma exceção que não foi levantada pelo código protegido pela construção com as instruções try …
except.
Quando uma exceção ocorre, ela pode estar associada a um valor chamado argumento da exceção. A presença e o
tipo do argumento dependem do tipo da exceção.
A cláusula except pode especificar uma variável depois do nome (ou da tupla de nomes) da exceção. A variável é
associada à instância de exceção capturada, com os argumentos armazenados em instancia.args. Por con-
veniência, a instância define o método __str__() para que os argumentos possam ser exibidos diretamente sem
necessidade de acessar .args. Pode-se também instanciar uma exceção antes de levantá-la e adicionar qualquer
atributo a ela, conforme desejado.
>>> try:
... raise Exception('spam', 'eggs')
... except Exception as inst:
... print(type(inst)) # the exception instance
... print(inst.args) # arguments stored in .args
... print(inst) # __str__ allows args to be printed directly,
... # but may be overridden in exception subclasses
... x, y = inst.args # unpack args
... print('x =', x)
... print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
Caso uma exceção tenha argumentos, os mesmos serão impressos como a última parte (‘detalhe’) da mensagem para
as exceções não tratadas.
Além disso, tratadores de exceção são capazes de capturar exceções que tenham sido levantadas no interior de funções
invocadas (mesmo que indiretamente) na cláusula try. Por exemplo:
A instrução raise permite ao programador forçar a ocorrência de um determinado tipo de exceção. Por exemplo:
O argumento de raise indica a exceção a ser levantada. Esse argumento deve ser uma instância de exceção ou uma
classe de exceção (uma classe que deriva de Exception). Se uma classe de exceção for passada, será implicitamente
instanciada invocando o seu construtor sem argumentos:
Caso você precise determinar se uma exceção foi levantada ou não, mas não quer manipular o erro, uma forma
simples de instrução raise permite que você levante-a novamente:
>>> try:
... raise NameError('HiThere')
... except NameError:
... print('An exception flew by!')
(continua na próxima página)
A instrução raise permite um from opcional que torna possível o encadear exceções. Por exemplo:
Isso pode ser útil quando você está transformando exceções. Por exemplo:
The above exception was the direct cause of the following exception:
O encadeamento de exceções acontece automaticamente quando uma exceção é gerada dentro de uma seção except
ou finally. O encadeamento de exceções pode ser desativado usando o idioma from None:
>>> try:
... open('database.sqlite')
... except IOError:
... raise RuntimeError from None
...
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError
Programas podem definir novos tipos de exceções, através da criação de uma nova classe (veja Classes para mais
informações sobre classes Python). Exceções devem ser derivadas da classe Exception, direta ou indiretamente.
Classes de exceções podem ser definidas para fazer qualquer coisa que qualquer outra classe faz, mas em geral são bem
simples, frequentemente oferecendo apenas alguns atributos que fornecem informações sobre o erro que ocorreu. Ao
criar um módulo que pode gerar diversos erros, uma prática comum é criar uma classe base para as exceções definidas
por aquele módulo, e as classes específicas para cada condição de erro como subclasses dela:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
É comum que novas exceções sejam definidas com nomes terminando em “Error”, semelhante a muitas exceções
embutidas.
Muitos módulos padrão definem novas exceções para reportar erros que ocorrem no interior das funções que definem.
Mais informações sobre classes aparecem no capítulo Classes.
A instrução try possui outra cláusula opcional, cuja finalidade é permitir a implementação de ações de limpeza, que
sempre devem ser executadas independentemente da ocorrência de exceções. Como no exemplo:
>>> try:
... raise KeyboardInterrupt
... finally:
... print('Goodbye, world!')
...
Goodbye, world!
KeyboardInterrupt
(continua na próxima página)
Se uma cláusula finally estiver presente, a cláusula finally será executada como a última tarefa antes da
conclusão da instrução try. A cláusula finally executa se a instrução try produz uma exceção. Os pontos a
seguir discutem casos mais complexos quando ocorre uma exceção:
• Se ocorrer uma exceção durante a execução da cláusula try, a exceção poderá ser tratada por uma cláusula
except. Se a exceção não for tratada por uma cláusula except, a exceção será gerada novamente após a
execução da cláusula: keyword:!finally.
• Uma exceção pode ocorrer durante a execução de uma cláusula except ou else. Novamente, a exceção é
re-levantada depois que finally é executada.
• Se a instrução try atingir uma instrução break, continue ou return, a cláusula finally será execu-
tada imediatamente antes da execução da instrução break, continue ou return.
• Se uma cláusula finally incluir uma instrução return, o valor retornado será aquele da instrução return
da cláusula finally, não o valor da instrução return da cláusula try.
Por exemplo:
Como você pode ver, a cláusula finally é executada em todos os casos. A exceção TypeError levantada pela
divisão de duas strings não é tratada pela cláusula except e portanto é re-levantada depois que a cláusula finally
é executada.
Em aplicação do mundo real, a cláusula finally é útil para liberar recursos externos (como arquivos ou conexões
de rede), independentemente do uso do recurso ter sido bem sucedido ou não.
Alguns objetos definem ações de limpeza padrões para serem executadas quando o objeto não é mais necessário,
independentemente da operação que estava usando o objeto ter sido ou não bem sucedida. Veja o exemplo a seguir,
que tenta abrir um arquivo e exibir seu conteúdo na tela.
O problema com esse código é que ele deixa o arquivo aberto um período indeterminado depois que o código é
executado. Isso não chega a ser problema em scripts simples, mas pode ser um problema para grandes aplicações.
A palavra reservada with permite que objetos como arquivos sejam utilizados com a certeza de que sempre serão
prontamente e corretamente finalizados.
with open("myfile.txt") as f:
for line in f:
print(line, end="")
Depois que a instrução é executada, o arquivo f é sempre fechado, mesmo se ocorrer um problema durante o pro-
cessamento das linhas. Outros objetos que, como arquivos, fornecem ações de limpeza predefinidas as indicarão em
suas documentações.
Classes
Classes proporcionam uma forma de organizar dados e funcionalidades juntos. Criar uma nova classe cria um novo
“tipo” de objeto, permitindo que novas “instâncias” desse tipo sejam produzidas. Cada instância da classe pode ter
atributos anexados a ela, para manter seu estado. Instâncias da classe também podem ter métodos (definidos pela
classe) para modificar seu estado.
Em comparação com outras linguagens de programação, o mecanismo de classes de Python introduz a programação
orientada a objetos sem acrescentar muitas novidades de sintaxe ou semântica. É uma mistura de mecanismos equi-
valentes encontrados em C++ e Modula-3. As classes em Python oferecem todas as características tradicionais da
programação orientada a objetos: o mecanismo de herança permite múltiplas classes base (herança múltipla), uma
classe derivada pode sobrescrever quaisquer métodos de uma classe ancestral, e um método pode invocar outro mé-
todo homônimo de uma classe ancestral. Objetos podem armazenar uma quantidade arbitrária de dados de qualquer
tipo. Assim como acontece com os módulos, as classes fazem parte da natureza dinâmica de Python: são criadas em
tempo de execução, e podem ser alteradas após sua criação.
Usando a terminologia de C++, todos os membros de uma classe (incluindo dados) são públicos (veja exceção abaixo
Variáveis privadas), e todos as funções membro são virtuais. Como em Modula-3, não existem atalhos para referen-
ciar membros do objeto de dentro dos seus métodos: o método (função definida em uma classe) é declarado com
um primeiro argumento explícito representando o objeto (instância da classe), que é fornecido implicitamente pela
chamada ao método. Como em Smalltalk, classes são objetos. Isso fornece uma semântica para importar e renomear.
Ao contrário de C++ ou Modula-3, tipos pré-definidos podem ser utilizados como classes base para extensões por
herança pelo usuário. Também, como em C++, a maioria dos operadores (aritméticos, indexação, etc) podem ser
redefinidos por instâncias de classe.
(Na falta de uma terminologia universalmente aceita para falar sobre classes, ocasionalmente farei uso de termos
comuns em Smalltalk ou C++. Eu usaria termos de Modula-3, já que sua semântica de orientação a objetos é mais
próxima da de Python, mas creio que poucos leitores já ouviram falar dessa linguagem.)
71
Python Tutorial, Release 3.9.1
Objetos têm individualidade, e vários nomes (em diferentes escopos) podem ser vinculados a um mesmo objeto. Isso
é chamado de apelidamento em outras linguagens. Geralmente, esta característica não é muito apreciada, e pode
ser ignorada com segurança ao lidar com tipos imutáveis (números, strings, tuplas). Entretanto, apelidamento pode
ter um efeito surpreendente na semântica do código Python envolvendo objetos mutáveis como listas, dicionários e
a maioria dos outros tipos. Isso pode ser usado em benefício do programa, porque os apelidos funcionam de certa
forma como ponteiros. Por exemplo, passar um objeto como argumento é barato, pois só um ponteiro é passado na
implementação; e se uma função modifica um objeto passado como argumento, o invocador verá a mudança — isso
elimina a necessidade de ter dois mecanismos de passagem de parâmetros como em Pascal.
Antes de introduzir classes, é preciso falar das regras de escopo em Python. Definições de classe fazem alguns
truques com espaços de nomes. Portanto, primeiro é preciso entender claramente como escopos e espaços de nomes
funcionam, para entender o que está acontecendo. Esse conhecimento é muito útil para qualquer programador Python
avançado.
Vamos começar com algumas definições.
Um espaço de nomes é um mapeamento que associa nomes a objetos. Atualmente, são implementados como dici-
onários em Python, mas isso não é perceptível (a não ser pelo desempenho), e pode mudar no futuro. Exemplos
de espaços de nomes são: o conjunto de nomes pré-definidos (funções como abs() e as exceções pré-definidas);
nomes globais em um módulo; e nomes locais na invocação de uma função. De certa forma, os atributos de um
objeto também formam um espaço de nomes. O mais importante é saber que não existe nenhuma relação entre
nomes em espaços de nomes distintos. Por exemplo, dois módulos podem definir uma função de nome maximize
sem confusão — usuários dos módulos devem prefixar a função com o nome do módulo, para evitar colisão.
A propósito, utilizo a palavra atributo para qualquer nome depois de um ponto. Na expressão z.real, por exem-
plo, real é um atributo do objeto z. Estritamente falando, referências para nomes em módulos são atributos: na
expressão modname.funcname, modname é um objeto módulo e funcname é um de seus atributos. Neste
caso, existe um mapeamento direto entre os atributos de um módulo e os nomes globais definidos no módulo: eles
compartilham o mesmo espaço de nomes!1
Atributos podem ser somente leitura ou para leitura e escrita. No segundo caso, é possível atribuir um novo valor ao
atributo. Atributos de módulos são passíveis de atribuição: você pode escrever modname.the_answer = 42.
Atributos que aceitam escrita também podem ser apagados através da instrução del. Por exemplo, del modname.
the_answer removerá o atributo the_answer do objeto referenciado por modname.
Espaços de nomes são criados em momentos diferentes e possuem diferentes ciclos de vida. O espaço de nomes
que contém os nomes embutidos é criado quando o interpretador inicializa e nunca é removido. O espaço de nomes
global de um módulo é criado quando a definição do módulo é lida, e normalmente duram até a terminação do
interpretador. Os comandos executados pela invocação do interpretador, pela leitura de um script com programa
principal, ou interativamente, são parte do módulo chamado __main__, e portanto possuem seu próprio espaço de
nomes. (Os nomes embutidos possuem seu próprio espaço de nomes no módulo chamado builtins.).
O espaço de nomes local de uma função é criado quando a função é invocada, e apagado quando a função retorna
ou levanta uma exceção que não é tratada na própria função. (Na verdade, uma forma melhor de descrever o que
realmente acontece é que o espaço de nomes local é “esquecido” quando a função termina.) Naturalmente, cada
invocação recursiva de uma função tem seu próprio espaço de nomes.
Um escopo é uma região textual de um programa Python onde um espaço de nomes é diretamente acessível. Aqui,
“diretamente acessível” significa que uma referência sem um prefixo qualificador permite o acesso ao nome.
Ainda que escopos sejam determinados estaticamente, eles são usados dinamicamente. A qualquer momento durante
a execução, existem 3 ou 4 escopos aninhados cujos espaços de nomes são diretamente acessíveis:
1 Exceto por uma coisa. Os objetos módulo têm um atributo secreto e somente para leitura chamado __dict__ que retorna o dicionário
usado para implementar o espaço de nomes do módulo; o nome __dict__ é um atributo, mas não um nome global. Obviamente, usar isso viola
a abstração da implementação do espaço de nomes, e deve ser restrito a coisas como depuradores post-mortem.
72 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
Este é um exemplo que demonstra como se referir aos diferentes escopos e aos espaços de nomes, e como global
e nonlocal pode afetar ligação entre as variáveis:
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
scope_test()
print("In global scope:", spam)
Observe como uma atribuição local (que é o padrão) não altera o vínculo de scope_test a spam. A instrução
nonlocal mudou o vínculo de scope_test de spam e a atribuição global alterou a ligação para o nível do módulo.
Você também pode ver que não havia nenhuma ligação anterior para spam antes da atribuição global.
As classes introduzem um pouco de nova sintaxe, três novos tipos de objeto e algumas semânticas novas.
Definições de classe, assim como definições de função (instruções def), precisam ser executadas antes que tenham
qualquer efeito. (Você pode colocar uma definição de classe dentro do teste condicional de um if ou dentro de uma
função.)
Na prática, as instruções dentro da definição de classe geralmente serão definições de funções, mas outras instruções
são permitidas, e às vezes são bem úteis — voltaremos a este tema depois. Definições de funções dentro da classe
normalmente têm um forma peculiar de lista de argumentos, determinada pela convenção de chamada a métodos —
isso também será explicado mais tarde.
Quando se inicia a definição de classe, um novo espaço de nomes é criado, e usado como escopo local — assim, todas
atribuições a variáveis locais ocorrem nesse espaço de nomes. Em particular, funções definidas aqui são vinculadas a
nomes nesse escopo.
Quando uma definição de classe é finalizada normalmente (até o fim), um objeto classe é criado. Este objeto encapsula
o conteúdo do espaço de nomes criado pela definição da classe; aprenderemos mais sobre objetos classe na próxima
seção. O escopo local que estava vigente antes da definição da classe é reativado, e o objeto classe é vinculado ao
identificador da classe nesse escopo (ClassName no exemplo).
def f(self):
return 'hello world'
74 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
então MyClass.i e MyClass.f são referências a atributo válidas, retornando, respectivamente, um inteiro e um
objeto função. Atributos de classe podem receber valores, pode-se modificar o valor de MyClass.i num atribuição.
__doc__ também é um atributo válido da classe, retornando a documentação associada: "A simple example
class".
Para instanciar uma classe, usa-se a mesma sintaxe de invocar uma função. Apenas finja que o objeto classe do
exemplo é uma função sem parâmetros, que devolve uma nova instância da classe. Por exemplo (assumindo a classe
acima):
x = MyClass()
cria uma nova instância da classe e atribui o objeto resultante à variável local x.
A operação de instanciação (“invocar” um objeto classe) cria um objeto vazio. Muitas classes preferem criar no-
vos objetos com um estado inicial predeterminado. Para tanto, a classe pode definir um método especial chamado
__init__(), assim:
def __init__(self):
self.data = []
Quando uma classe define um método __init__(), o processo de instanciação automaticamente invoca
__init__() sobre a instância recém criada. Em nosso exemplo, uma nova instância já inicializada pode ser
obtida desta maneira:
x = MyClass()
Naturalmente, o método __init__() pode ter parâmetros para maior flexibilidade. Neste caso, os argumentos
fornecidos na invocação da classe serão passados para o método __init__(). Por exemplo,
Agora o que podemos fazer com objetos de instância? As únicas operações compreendidas por objetos de instância
são os atributos de referência. Existem duas maneiras válidas para nomear atributos: atributos de dados e métodos.
Atributos de dados correspondem a “variáveis de instância” em Smalltalk, e a “membros de dados” em C++. Atributos
de dados não precisam ser declarados. Assim como variáveis locais, eles passam a existir na primeira vez em que é
feita uma atribuição. Por exemplo, se x é uma instância da MyClass criada acima, o próximo trecho de código irá
exibir o valor 16, sem deixar nenhum rastro:
x.counter = 1
while x.counter < 10:
x.counter = x.counter * 2
print(x.counter)
del x.counter
O outro tipo de referências a atributos de instância é o “método”. Um método é uma função que “pertence” a um
objeto instância. (Em Python, o termo método não é aplicado exclusivamente a instâncias de classes definidas pelo
usuário: outros tipos de objetos também podem ter métodos. Por exemplo, listas possuem os métodos append, insert,
remove, sort, entre outros. Porém, na discussão a seguir, usaremos o termo método apenas para se referir a métodos
de classes definidas pelo usuário. Seremos explícitos ao falar de outros métodos.)
Nomes de métodos válidos de uma instância dependem de sua classe. Por definição, cada atributo de uma classe que
é uma função corresponde a um método das instâncias. Em nosso exemplo, x.f é uma referência de método válida
já que MyClass.f é uma função, enquanto x.i não é, já que MyClass.i não é uma função. Entretanto, x.f
não é o mesmo que MyClass.f. A referência x.f acessa um objeto método e a MyClass.f acessa um objeto
função.
x.f()
No exemplo MyClass o resultado da expressão acima será a string 'hello world'. No entanto, não é obri-
gatório invocar o método imediatamente: como x.f é também um objeto ele pode ser atribuído a uma variável e
invocado depois. Por exemplo:
xf = x.f
while True:
print(xf())
De forma geral, variáveis de instância são variáveis que indicam dados que são únicos a cada instância individual, e
variáveis de classe são variáveis de atributos e de métodos que são comuns a todas as instâncias de uma classe:
class Dog:
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # shared by all dogs
'canine'
>>> e.kind # shared by all dogs
'canine'
>>> d.name # unique to d
'Fido'
(continua na próxima página)
76 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
Como vimos em Uma palavra sobre nomes e objetos, dados compartilhados podem causar efeitos inesperados quando
envolvem objetos (mutáveis), como listas ou dicionários. Por exemplo, a lista tricks do código abaixo não deve ser
usada como variável de classe, pois assim seria compartilhada por todas as instâncias de Dog:
class Dog:
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks # unexpectedly shared by all dogs
['roll over', 'play dead']
Em vez disso, o modelo correto da classe deve usar uma variável de instância:
class Dog:
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']
Se um mesmo nome de atributo ocorre tanto na instância quanto na classe, a busca pelo atributo prioriza a instância:
>>> class Warehouse:
purpose = 'storage'
region = 'west'
>>> w1 = Warehouse()
>>> print(w1.purpose, w1.region)
storage west
>>> w2 = Warehouse()
>>> w2.region = 'east'
>>> print(w2.purpose, w2.region)
storage east
Atributos de dados podem ser referenciados por métodos da própria instância, bem como por qualquer outro usuário
do objeto (também chamados “clientes” do objeto). Em outras palavras, classes não servem para implementar tipos
puramente abstratos de dados. De fato, nada em Python torna possível assegurar o encapsulamento de dados — tudo
é baseado em convenção. (Por outro lado, a implementação de Python, escrita em C, pode esconder completamente
detalhes de um objeto e controlar o acesso ao objeto, se necessário; isto pode ser utilizado por extensões de Python
escritas em C.)
Clientes devem utilizar atributos de dados com cuidado, pois podem bagunçar invariantes assumidas pelos métodos ao
esbarrar em seus atributos de dados. Note que clientes podem adicionar atributos de dados a suas próprias instâncias,
sem afetar a validade dos métodos, desde que seja evitado o conflito de nomes. Novamente, uma convenção de
nomenclatura poupa muita dor de cabeça.
Não existe atalho para referenciar atributos de dados (ou outros métodos!) de dentro de um método. Isso aumenta a
legibilidade dos métodos: não há como confundir variáveis locais com variáveis da instância quando lemos rapida-
mente um método.
Frequentemente, o primeiro argumento de um método é chamado self. Isso não passa de uma convenção: o
identificador self não é uma palavra reservada nem possui qualquer significado especial em Python. Mas note que,
ao seguir essa convenção, seu código se torna legível por uma grande comunidade de desenvolvedores Python e é
possível que alguma IDE dependa dessa convenção para analisar seu código.
Qualquer objeto função que é atributo de uma classe, define um método para as instâncias dessa classe. Não é
necessário que a definição da função esteja textualmente embutida na definição da classe. Atribuir um objeto função
a uma variável local da classe é válido. Por exemplo:
class C:
f = f1
def g(self):
return 'hello world'
h = g
Agora f, g e h são todos atributos da classe C que referenciam funções, e consequentemente são todos métodos de
instâncias da classe C, onde h é exatamente equivalente a g. No entanto, essa prática serve apenas para confundir o
leitor do programa.
Métodos podem invocar outros métodos usando atributos de método do argumento self:
class Bag:
def __init__(self):
self.data = []
Métodos podem referenciar nomes globais da mesma forma que funções comuns. O escopo global associado a um
método é o módulo contendo sua definição na classe (a classe propriamente dita nunca é usada como escopo global!).
Ainda que seja raro justificar o uso de dados globais em um método, há diversos usos legítimos do escopo global.
Por exemplo, funções e módulos importados no escopo global podem ser usados por métodos, bem como as funções
e classes definidas no próprio escopo global. Provavelmente, a classe contendo o método em questão também foi
definida neste escopo global. Na próxima seção veremos razões pelas quais um método pode querer referenciar sua
própria classe.
Cada valor é um objeto e, portanto, tem uma classe (também chamada de tipo). Ela é armazenada como object.
78 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
__class__.
9.5 Herança
Obviamente, uma característica da linguagem não seria digna do nome “classe” se não suportasse herança. A sintaxe
para uma classe derivada é assim:
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
O identificador BaseClassName deve estar definido no escopo que contém a definição da classe derivada. No
lugar do nome da classe base, também são aceitas outras expressões. Isso é muito útil, por exemplo, quando a classe
base é definida em outro módulo:
class DerivedClassName(modname.BaseClassName):
A execução de uma definição de classe derivada procede da mesma forma que a de uma classe base. Quando o objeto
classe é construído, a classe base é lembrada. Isso é utilizado para resolver referências a atributos. Se um atributo
requisitado não for encontrado na classe, ele é procurado na classe base. Essa regra é aplicada recursivamente se a
classe base por sua vez for derivada de outra.
Não há nada de especial sobre instanciação de classes derivadas: DerivedClassName() cria uma nova instância
da classe. Referências a métodos são resolvidas da seguinte forma: o atributo correspondente é procurado através da
cadeia de classes base, e referências a métodos são válidas se essa procura produzir um objeto função.
Classes derivadas podem sobrescrever métodos das suas classes base. Uma vez que métodos não possuem privilégios
especiais quando invocam outros métodos no mesmo objeto, um método na classe base que invoca um outro método
da mesma classe base pode, efetivamente, acabar invocando um método sobreposto por uma classe derivada. (Para
programadores C++ isso significa que todos os métodos em Python são realmente virtuais.)
Um método sobrescrito em uma classe derivada, de fato, pode querer estender, em vez de simplesmente substituir,
o método da classe base, de mesmo nome. Existe uma maneira simples de chamar diretamente o método da classe
base: apenas chame BaseClassName.methodname(self, arguments). Isso é geralmente útil para os
clientes também. (Note que isto só funciona se a classe base estiver acessível como BaseClassName no escopo
global).
Python tem duas funções embutidas que trabalham com herança:
• Use isinstance() para verificar o tipo de uma instância: isinstance(obj, int) será True so-
mente se obj.__class__ é a classe int ou alguma classe derivada de int.
• Use issubclass() para verificar herança entre classes: issubclass(bool, int) é True porque
bool é uma subclasse de int. Porém, issubclass(float, int) é False porque float não é uma
subclasse de int.
Python também suporta uma forma de herança múltipla. Uma definição de classe com várias classes bases tem esta
forma:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
9.5. Herança 79
Python Tutorial, Release 3.9.1
Para a maioria dos casos mais simples, pense na pesquisa de atributos herdados de uma classe pai como o primeiro
nível de profundidade, da esquerda para a direita, não pesquisando duas vezes na mesma classe em que há uma
sobreposição na hierarquia. Assim, se um atributo não é encontrado em DerivedClassName, é procurado em
Base1, depois, recursivamente, nas classes base de Base1, e se não for encontrado lá, é pesquisado em Base2 e
assim por diante.
De fato, é um pouco mais complexo que isso; a ordem de resolução de métodos muda dinamicamente para suportar
chamadas cooperativas para super(). Essa abordagem é conhecida em outras linguagens de herança múltipla como
chamar-o-próximo-método, e é mais poderosa que a chamada à função super, encontrada em linguagens de herança
única.
A ordenação dinâmica é necessária porque todos os casos de herança múltipla exibem um ou mais relacionamentos
de diamante (em que pelo menos uma das classes pai pode ser acessada por meio de vários caminhos da classe mais
inferior). Por exemplo, todas as classes herdam de object, portanto, qualquer caso de herança múltipla fornece
mais de um caminho para alcançar object. Para evitar que as classes base sejam acessadas mais de uma vez,
o algoritmo dinâmico lineariza a ordem de pesquisa, de forma a preservar a ordenação da esquerda para a direita,
especificada em cada classe, que chama cada pai apenas uma vez, e que é monotônica (significando que uma classe
pode ser subclassificada sem afetar a ordem de precedência de seus pais). Juntas, essas propriedades tornam possível
projetar classes confiáveis e extensíveis com herança múltipla. Para mais detalhes, veja https://www.python.org/
download/releases/2.3/mro/.
Variáveis de instância “privadas”, que não podem ser acessadas, exceto em métodos do próprio objeto, não existem
em Python. No entanto, existe uma convenção que é seguida pela maioria dos programas em Python: um nome
prefixado com um sublinhado (por exemplo: _spam ) deve ser tratado como uma parte não-pública da API (seja
uma função, um método ou um atributo de dados). Tais nomes devem ser considerados um detalhe de implementação
e sujeito a alteração sem aviso prévio.
Uma vez que existe um caso de uso válido para a definição de atributos privados em classes (especificamente para
evitar conflitos com nomes definidos em subclasses), existe um suporte limitado a identificadores privados em classes,
chamado desfiguração de nomes. Qualquer identificador no formato __spam (pelo menos dois sublinhados no início,
e no máximo um sublinhado no final) é textualmente substituído por _classname__spam, onde classname
é o nome da classe atual com sublinhado(s) iniciais omitidos. Essa desfiguração independe da posição sintática do
identificador, desde que ele apareça dentro da definição de uma classe.
A desfiguração de nomes é útil para que subclasses possam sobrescrever métodos sem quebrar invocações de métodos
dentro de outra classe. Por exemplo:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
class MappingSubclass(Mapping):
O exemplo acima deve funcionar mesmo se MappingSubclass introduzisse um identificador __update uma
vez que é substituído por _Mapping__update na classe Mapping e _MappingSubclass__update na
80 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
Às vezes, é útil ter um tipo semelhante ao “record” de Pascal ou ao “struct” de C, para agrupar alguns itens de dados.
Uma definição de classe vazia funciona bem para este fim:
class Employee:
pass
Um trecho de código Python que espera um tipo de dado abstrato em particular, pode receber, ao invés disso, uma
classe que imita os métodos que aquele tipo suporta. Por exemplo, se você tem uma função que formata dados obtidos
de um objeto do tipo “arquivo”, pode definir uma classe com métodos read() e readline() que obtém os dados
de um “buffer de caracteres” e passar como argumento.
Métodos de instância tem atributos também: m.__self__ é o objeto instância com o método m(), e m.
__func__ é o objeto função correspondente ao método.
9.8 Iteradores
Você já deve ter notado que pode usar laços for com a maioria das coleções em Python:
Esse estilo de acesso é claro, conciso e conveniente. O uso de iteradores permeia e unifica o Python. Nos bas-
tidores, a instrução for chama iter() no objeto contêiner. A função retorna um objeto iterador que define
o método __next__() que acessa elementos no contêiner, um de cada vez. Quando não há mais elementos,
__next__() levanta uma exceção StopIteration que informa ao for para terminar. Você pode chamar o
método __next__() usando a função embutida next(); este exemplo mostra como tudo funciona:
>>> s = 'abc'
>>> it = iter(s)
(continua na próxima página)
Observando o mecanismo por trás do protocolo dos iteradores, fica fácil adicionar esse comportamento às suas classes.
Defina um método __iter__() que retorna um objeto que tenha um método __next__(). Se uma classe já
define __next__(), então __iter__() pode simplesmente retornar self:
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
9.9 Geradores
Geradores são uma ferramenta simples e poderosa para criar iteradores. São escritos como funções normais mas
usam a instrução yield quando precisam retornar dados. Cada vez que next() é chamado, o gerador volta ao
ponto onde parou (lembrando todos os valores de dados e qual instrução foi executada pela última vez). Um exemplo
mostra como geradores podem ser trivialmente fáceis de criar:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
82 Capítulo 9. Classes
Python Tutorial, Release 3.9.1
Qualquer coisa que possa ser feita com geradores também pode ser feita com iteradores baseados numa classe, como
descrito na seção anterior. O que torna geradores tão compactos é que os métodos __iter__() e __next__()
são criados automaticamente.
Outro ponto chave é que as variáveis locais e o estado da execução são preservados automaticamente entre as cha-
madas. Isto torna a função mais fácil de escrever e muito mais clara do que uma implementação usando variáveis de
instância como self.index e self.data.
Além disso, quando geradores terminam, eles levantam StopIteration automaticamente. Combinados, todos
estes aspectos tornam a criação de iteradores tão fácil quanto escrever uma função normal.
Alguns geradores simples podem ser codificados, de forma sucinta, como expressões, usando uma sintaxe semelhante
a compreensões de lista, mas com parênteses em vez de colchetes. Essas expressões são projetadas para situações em
que o gerador é usado imediatamente, pela função que o engloba. As expressões geradoras são mais compactas, mas
menos versáteis do que as definições completas do gerador, e tendem a usar menos memória do que as compreensões
de lista equivalentes.
Exemplos:
84 Capítulo 9. Classes
CAPÍTULO 10
>>> import os
>>> os.getcwd() # Return the current working directory
'C:\\Python39'
>>> os.chdir('/server/accesslogs') # Change current working directory
>>> os.system('mkdir today') # Run the command mkdir in the system shell
0
Certifique-se de usar a forma import os ao invés de from os import *. Isso evitará que os.open()
oculte a função open() que opera de forma muito diferente.
As funções embutidas dir() e help() são úteis como um sistema de ajuda interativa para lidar com módulos
grandes como os:
>>> import os
>>> dir(os)
<returns a list of all module functions>
>>> help(os)
<returns an extensive manual page created from the module's docstrings>
Para tarefas de gerenciamento cotidiano de arquivos e diretórios, o módulo shutil fornece uma interface de alto
nível que é mais simples de usar:
85
Python Tutorial, Release 3.9.1
O módulo glob fornece uma função para criar listas de arquivos a partir de buscas em diretórios usando caracteres
curinga:
Scripts geralmente precisam processar argumentos passados na linha de comando. Esses argumentos são armazena-
dos como uma lista no atributo argv do módulo sys. Por exemplo, teríamos a seguinte saída executando python
demo.py one two three na linha de comando:
O módulo argparse fornece um mecanismo mais sofisticado para processar argumentos de linha de comando. O
script seguinte extrai e exibe um ou mais nomes de arquivos e um número de linhas opcional:
import argparse
Quando executada a linha de comando python top.py --lines=5 alpha.txt beta.txt, o script de-
fine args.lines para 5 e args.filenames para ['alpha.txt', 'beta.txt'].
O módulo sys também possui atributos para stdin, stdout e stderr. O último é usado para emitir avisos e mensagens
de erros visíveis mesmo quando stdout foi redirecionado:
O módulo re fornece ferramentas para lidar com processamento de strings através de expressões regulares. Para
reconhecimento de padrões complexos, expressões regulares oferecem uma solução sucinta e eficiente:
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
Quando as exigências são simples, métodos de strings são preferíveis por serem mais fáceis de ler e depurar:
10.6 Matemática
O módulo math oferece acesso às funções da biblioteca C para matemática de ponto flutuante:
O módulo statistics calcula as propriedades estatísticas básicas (a média, a mediana, a variação, etc.) de dados
numéricos:
O projeto SciPy <https://scipy.org> tem muitos outros módulos para cálculos numéricos.
Há diversos módulos para acesso e processamento de protocolos da internet. Dois dos mais simples são urllib.
request para efetuar download de dados a partir de URLs e smtplib para enviar mensagens de correio eletrônico:
10.6. Matemática 87
Python Tutorial, Release 3.9.1
O módulo datetime fornece classes para manipulação de datas e horas nas mais variadas formas. Apesar da
disponibilidade de aritmética com data e hora, o foco da implementação é na extração eficiente dos membros para
formatação e manipulação. O módulo também oferece objetos que levam os fusos horários em consideração.
Formatos comuns de arquivamento e compressão de dados estão disponíveis diretamente através de alguns módulos,
entre eles: zlib, gzip, bz2, lzma, zipfile and tarfile.
Alguns usuários de Python desenvolvem um interesse profundo pelo desempenho relativo de diferentes abordagens
para o mesmo problema. Python oferece uma ferramenta de medição que esclarece essas dúvidas rapidamente.
Por exemplo, pode ser tentador usar o empacotamento e desempacotamento de tuplas ao invés da abordagem tradici-
onal de permutar os argumentos. O módulo timeit rapidamente mostra uma modesta vantagem de desempenho:
Em contraste com a granularidade fina do módulo timeit, os módulos profile e pstats oferecem ferramentas
para identificar os trechos mais críticos em grandes blocos de código.
Uma das abordagens usadas no desenvolvimento de software de alta qualidade é escrever testes para cada função à
medida que é desenvolvida e executar esses testes frequentemente durante o processo de desenvolvimento.
O módulo doctest oferece uma ferramenta para realizar um trabalho de varredura e validação de testes escritos
nas strings de documentação (docstrings) de um programa. A construção dos testes é tão simples quanto copiar uma
chamada típica juntamente com seus resultados e colá-los na docstring. Isto aprimora a documentação, fornecendo
ao usuário um exemplo real, e permite que o módulo doctest verifique se o código continua fiel à documentação:
def average(values):
"""Computes the arithmetic mean of a list of numbers.
import doctest
doctest.testmod() # automatically validate the embedded tests
O módulo unittest não é tão simples de usar quanto o módulo doctest, mas permite que um conjunto muito
maior de testes seja mantido em um arquivo separado:
import unittest
class TestStatisticalFunctions(unittest.TestCase):
def test_average(self):
self.assertEqual(average([20, 30, 70]), 40.0)
self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
average([])
with self.assertRaises(TypeError):
average(20, 30, 70)
Python tem uma filosofia de “baterias incluídas”. Isso fica mais evidente através da sofisticação e robustez dos seus
maiores pacotes. Por exemplo:
• Os módulos xmlrpc.client e xmlrpc.server tornam a implementação de chamadas remotas (remote
procedure calls) em uma tarefa quase trivial. Apesar dos nomes dos módulos, nenhum conhecimento direto
ou manipulação de XML é necessário.
• O pacote email é uma biblioteca para gerenciamento de mensagens de correio eletrônico, incluindo MIME
e outros baseados no RFC 2822. Diferente dos módulos smtplib e poplib que apenas enviam e rece-
bem mensagens, o pacote de email tem um conjunto completo de ferramentas para construir ou decodificar
a estrutura de mensagens complexas (incluindo anexos) e para implementação de protocolos de codificação e
cabeçalhos.
• O pacote json oferece um suporte robusto para analisar este popular formato para troca de dados. O módulo
csv oferece suporte para leitura e escrita direta em arquivos no formato Comma-Separated Value, comumente
suportado por bancos de dados e planilhas. O processamento XML é fornecido pelos pacotes xml.etree.
ElementTree, xml.dom e xml.sax. Juntos, esses módulos e pacotes simplificam muito a troca de
informações entre aplicativos Python e outras ferramentas.
• O módulo sqlite3 é um wrapper para a biblioteca de banco de dados SQLite, fornecendo um banco de
dados persistente que pode ser atualizado e acessado usando sintaxe SQL ligeiramente fora do padrão.
• Internacionalização está disponível através de diversos módulos, como gettext, locale, e o pacote
codecs.
Este segundo passeio apresenta alguns módulos avançados que atendem necessidades de programação profissional.
Estes módulos raramente aparecem em scripts pequenos.
O módulo reprlib fornece uma versão de repr() personalizado para exibições abreviadas de contêineres grandes
ou profundamente aninhados:
O módulo pprint oferece um controle mais sofisticado na exibição tanto de objetos embutidos quanto aqueles
criados pelo usuário de maneira que fique legível para o interpretador. Quando o resultado é maior que uma linha, o
“pretty printer” acrescenta quebras de linha e indentação para revelar as estruturas de maneira mais clara:
O módulo textwrap formata parágrafos de texto para que caibam em uma dada largura de tela:
91
Python Tutorial, Release 3.9.1
O módulo locale acessa uma base de dados de formatos específicos a determinada cultura. O atributo de agrupa-
mento da função “format” oferece uma forma direta de formatar números com separadores de grupo:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'English_United States.1252')
'English_United States.1252'
>>> conv = locale.localeconv() # get a mapping of conventions
>>> x = 1234567.8
>>> locale.format("%d", x, grouping=True)
'1,234,567'
>>> locale.format_string("%s%.*f", (conv['currency_symbol'],
... conv['frac_digits'], x), grouping=True)
'$1,234,567.80'
módulo string inclui a versátil classe Template com uma sintaxe simplificada, adequada para ser editada por
usuários finais. Isso permite que usuários personalizem suas aplicações sem a necessidade de alterar a aplicação.
Em um template são colocadas marcações indicando o local onde o texto variável deve ser inserido. Uma marcação
é formada por $ seguido de um identificador Python válido (caracteres alfanuméricos e underscores). Envolvendo-
se o identificador da marcação entre chaves, permite que ele seja seguido por mais caracteres alfanuméricos sem a
necessidade de espaços. Escrevendo-se $$ cria-se um único $:
>>> from string import Template
>>> t = Template('${village}folk send $$10 to $cause.')
>>> t.substitute(village='Nottingham', cause='the ditch fund')
'Nottinghamfolk send $10 to the ditch fund.'
O método substitute() levanta uma exceção KeyError quando o identificador de uma marcação não é for-
necido em um dicionário ou em um argumento nomeado (keyword argument). Para aplicações que podem receber
dados incompletos fornecidos pelo usuário, o método safe_substitute() pode ser mais apropriado — deixará
os marcadores intactos se os dados estiverem faltando:
>>> t = Template('Return the $item to $owner.')
>>> d = dict(item='unladen swallow')
>>> t.substitute(d)
Traceback (most recent call last):
...
KeyError: 'owner'
>>> t.safe_substitute(d)
'Return the unladen swallow to $owner.'
Subclasses de Template podem especificar um delimitador personalizado. Por exemplo, um utilitário para renome-
ação em lote de fotos pode usar o sinal de porcentagem para marcações como a data atual, número sequencial da
imagem ou formato do aquivo:
>>> import time, os.path
>>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
>>> class BatchRename(Template):
... delimiter = '%'
>>> fmt = input('Enter rename style (%d-date %n-seqnum %f-format): ')
Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f
Outra aplicação para templates é separar a lógica da aplicação dos detalhes de múltiplos formatos de saída. Assim é
possível usar templates personalizados para gerar arquivos XML, relatórios em texto puro e relatórios web em HTML.
O módulo struct oferece as funções pack() e unpack() para trabalhar com registros binários de tamanho
variável. O exemplo a seguir mostra como iterar através do cabeçalho de informação num aquivo ZIP sem usar o
módulo zipfile. Os códigos de empacotamento "H" e "I" representam números sem sinal de dois e quatro bytes
respectivamente. O "<" indica que os números têm tamanho padrão e são little-endian (bytes menos significativos
primeiro):
import struct
start = 0
for i in range(3): # show the first 3 file headers
start += 14
fields = struct.unpack('<IIIHH', data[start:start+16])
crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
start += 16
filename = data[start:start+filenamesize]
start += filenamesize
extra = data[start:start+extra_size]
print(filename, hex(crc32), comp_size, uncomp_size)
11.4 Multi-threading
O uso de threads é uma técnica para desacoplar tarefas que não são sequencialmente dependentes. Threads podem
ser usadas para melhorar o tempo de resposta de aplicações que aceitam entradas do usuário enquanto outras tarefas
são executadas em segundo plano. Um caso relacionado é executar ações de entrada e saída (I/O) em uma thread
paralelamente a cálculos em outra thread.
O código a seguir mostra como o módulo de alto nível threading pode executar tarefas em segundo plano enquanto
o programa principal continua a sua execução:
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
(continua na próxima página)
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print('Finished background zip of:', self.infile)
O principal desafio para as aplicações que usam múltiplas threads é coordenar as threads que compartilham dados
ou outros recursos. Para esta finalidade, o módulo threading oferece alguns mecanismos primitivos de sincronização,
como travas (locks), eventos, variáveis de condição e semáforos.
Ainda que todas essas ferramentas sejam poderosas, pequenos erros de design podem resultar em problemas difíceis
de serem diagnosticados. Por isso, a abordagem preferida para a coordenação da tarefa é concentrar todo o acesso a
um recurso em um único tópico e, em seguida, usar o módulo queue para alimentar esse segmento com solicitações
de outros tópicos. Aplicações que utilizam objetos Queue para comunicação e coordenação inter-thread são mais
fáceis de serem projetados, mais legíveis e mais confiáveis.
O módulo logging oferece um completo e flexível sistema de log. Da maneira mais simples, mensagens de log são
enviadas para um arquivo ou para sys.stderr:
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
Por padrão, mensagens informativas e de depuração são suprimidas e a saída é enviada para a saída de erros padrão
(stderr). Outras opções de saída incluem envio de mensagens através de correio eletrônico, datagramas, sockets
ou para um servidor HTTP. Novos filtros podem selecionar diferentes formas de envio de mensagens, baseadas na
prioridade da mensagem: DEBUG, INFO, WARNING, ERROR e CRITICAL.
O sistema de log pode ser configurado diretamente do Python ou pode ser carregado a partir de um arquivo de
configuração editável pelo usuário para logs personalizados sem a necessidade de alterar a aplicação.
Python faz gerenciamento automático de memória (contagem de referências para a maioria dos objetos e garbage
collection [coleta de lixo] para eliminar ciclos). A memória ocupada por um objeto é liberada logo depois da última
referência a ele ser eliminada.
Essa abordagem funciona bem para a maioria das aplicações, mas ocasionalmente surge a necessidade de rastrear
objetos apenas enquanto estão sendo usados por algum outro. Infelizmente rastreá-los cria uma referência, e isso
os fazem permanentes. O módulo weakref oferece ferramentas para rastrear objetos sem criar uma referência.
Quando o objeto não é mais necessário, ele é automaticamente removido de uma tabela de referências fracas e uma
chamada (callback) é disparada. Aplicações típicas incluem cacheamento de objetos que são muito custosos para
criar:
Muitas necessidades envolvendo estruturas de dados podem ser satisfeitas com o tipo embutido lista. Entretanto,
algumas vezes há uma necessidade por implementações alternativas que sacrificam algumas facilidades em nome de
melhor desempenho.
O módulo array oferece uma classe array, semelhante a uma lista, mas que armazena apenas dados homogêneos
e de maneira mais compacta. O exemplo a seguir mostra um vetor de números armazenados como números binários
de dois bytes sem sinal (código de tipo "H") ao invés dos 16 bytes usuais para cada item em uma lista de int:
O módulo collections oferece um objeto deque() que comporta-se como uma lista mas com appends e pops
pela esquerda mais rápidos, porém mais lento ao percorrer o meio da sequência. Esses objetos são adequados para
implementar filas e buscas de amplitude em árvores de dados (breadth first tree searches):
unsearched = deque([starting_node])
def breadth_first_search(unsearched):
node = unsearched.popleft()
for m in gen_moves(node):
if is_goal(m):
return m
unsearched.append(m)
Além de implementações alternativas de listas, a biblioteca também oferece outras ferramentas como o módulo
bisect com funções para manipulação de listas ordenadas:
O módulo heapq oferece funções para implementação de heaps baseadas em listas normais. O valor mais baixo é
sempre mantido na posição zero. Isso é útil para aplicações que acessam repetidamente o menor elemento, mas não
querem reordenar a lista toda a cada acesso:
O módulo decimal oferece o tipo Decimal para aritmética decimal com ponto flutuante. Comparado a imple-
mentação embutida float que usa aritmética binária de ponto flutuante, a classe é especialmente útil para:
• aplicações financeiras que requerem representação decimal exata,
• controle sobre a precisão,
• controle sobre arredondamento para satisfazer requisitos legais,
• rastreamento de casas decimais significativas, ou
• aplicações onde o usuário espera que os resultados sejam os mesmos que os dos cálculos feitos à mão.
Por exemplo, calcular um imposto de 5% sobre uma chamada telefônica de 70 centavos devolve diferentes resul-
tados com aritmética de ponto flutuante decimal ou binária. A diferença torna-se significativa se os resultados são
arredondados para o centavo mais próximo:
O resultado de Decimal considera zeros à direita, automaticamente inferindo quatro casas decimais a partir de
multiplicandos com duas casas decimais. O módulo Decimal reproduz a aritmética como fazemos à mão e evita pro-
blemas que podem ocorrer quando a representação binária do ponto flutuante não consegue representar quantidades
decimais com exatidão.
A representação exata permite à classe Decimal executar cálculos de módulo e testes de igualdade que não funci-
onam bem em ponto flutuante binário:
>>> getcontext().prec = 36
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857')
12.1 Introdução
Aplicações em Python normalmente usam pacotes e módulos que não vêm como parte da instalação padrão. Apli-
cações às vezes necessitam uma versão específica de uma biblioteca, porque ela requer que algum problema em
particular tenha sido consertado ou foi escrita utilizando-se de uma versão obsoleta da interface da biblioteca.
Isso significa que talvez não seja possível que uma instalação Python preencha os requisitos de qualquer aplicação.
Se uma aplicação A necessita a versão 1.0 de um módulo particular mas a aplicação B necessita a versão 2.0, os
requisitos entrarão em conflito e instalar qualquer uma das duas versões 1.0 ou 2.0 fará com que uma das aplicações
não consiga executar.
A solução para este problema é criar um ambiente virtual, uma árvore de diretórios que contém uma instalação Python
para uma versão particular do Python, além de uma série de pacotes adicionais.
Diferentes aplicações podem então usar diferentes ambientes virtuais. Para resolver o exemplo anterior de requisitos
conflitantes, a aplicação A deve ter seu próprio ambiente virtual com a versão 1.0 instalada enquanto a aplicação B
vai possuir outro ambiente virtual com a versão 2.0. Se a aplicação B precisar fazer uma atualização para a versão
3.0, isso não afetará o ambiente da aplicação A.
O módulo usado para criar e gerenciar ambientes virtuais é chamado venv. O venv normalmente irá instalar a
versão mais recente de Python que você tiver disponível. Se você tiver múltiplas versões de Python no seu sistema,
você pode selecionar uma versão específica do Python executando python3 ou qualquer versão que você desejar.
Para criar um ambiente virtual, escolha um diretório onde deseja colocá-lo e execute o módulo venv como um script
com o caminho do diretório:
Isso irá criar o diretório tutorial-env se ele não existir e também criará diretórios dentro dele contendo uma
cópia do interpretador Python, a biblioteca padrão e diversos arquivos de suporte.
Um diretório de localização comum para um ambiente virtual é .venv. Esse nome tipicamente mantém o diretório
oculto em seu ambiente, portanto é transparente, ao menos tempo que explica o motivo desse diretório existir. Tam-
bém previne conflitos com .env, arquivos de definição de variáveis de ambiente que algumas ferramentas utilizam.
99
Python Tutorial, Release 3.9.1
tutorial-env\Scripts\activate.bat
source tutorial-env/bin/activate
(Este script é escrito para o shell bash. Se você usa shells csh ou fish, existem scripts alternativos activate.
csh e activate.fish para utilização.)
Ao ativar seu ambiente virtual haverá uma mudança no prompt do shell para mostrar qual ambiente virtual você
está usando e modificará o ambiente para que quando você executar python ativar a versão e instalação do Python
particular àquele ambiente. Por exemplo:
$ source ~/envs/tutorial-env/bin/activate
(tutorial-env) $ python
Python 3.5.1 (default, May 6 2016, 10:59:36)
...
>>> import sys
>>> sys.path
['', '/usr/local/lib/python35.zip', ...,
'~/envs/tutorial-env/lib/python3.5/site-packages']
>>>
Você pode instalar, atualizar e remover pacotes usando um programa chamado pip. Por padrão pip irá instalar
pacotes do Python Package Index, <https://pypi.org>. Você pode navegar pelo Python Package Index através do seu
navegador web, ou usando os recursos limitados de busca do pip:
pip tem uma série de subcomandos: “search”, “install”, “uninstall”, “freeze”, etc. (Consulte o guia installing-index
para a documentação completa do pip.)
Você pode instalar a última versão de um pacote apenas especificando nome do pacote:
Você também pode instalar uma versão específica de um pacote dando o nome do pacote seguido por == e o número
da versão:
Se você re-executar esse comando, pip vai perceber que aquela versão requisitada já foi instalada e não fará
nada. Você pode definir uma versão diferente para instalar aquela versão ou você pode executar pip install
--upgrade para fazer a atualização do pacote para a última versão.
(tutorial-env) $ python -m pip install --upgrade requests
Collecting requests
Installing collected packages: requests
Found existing installation: requests 2.6.0
Uninstalling requests-2.6.0:
Successfully uninstalled requests-2.6.0
Successfully installed requests-2.7.0
pip uninstall seguido do nome de um ou mais pacotes irá remover os pacotes do ambiente virtual.
pip show irá mostrar informações sobre um pacote em particular:
(tutorial-env) $ pip show requests
---
Metadata-Version: 2.0
Name: requests
Version: 2.7.0
Summary: Python HTTP for Humans.
Home-page: http://python-requests.org
Author: Kenneth Reitz
Author-email: [email protected]
License: Apache 2.0
Location: /Users/akuchling/envs/tutorial-env/lib/python3.4/site-packages
Requires:
pip list irá apresentar uma lista de todos os pacotes instalados no ambiente virtual.
(tutorial-env) $ pip list
novas (3.1.1.3)
numpy (1.9.2)
pip (7.0.3)
requests (2.7.0)
setuptools (16.0)
pip freeze irá mostrar uma lista dos pacotes instalados, mas o resultado usa o formato que o pip install
aceita. Uma convenção comum é colocar essa lista em um arquivo chamado requirements.txt:
(tutorial-env) $ pip freeze > requirements.txt
(tutorial-env) $ cat requirements.txt
novas==3.1.1.3
numpy==1.9.2
requests==2.7.0
O arquivo requirements.txt pode ser submetido no controle de versão e adicionado como parte da aplicação.
Usuários poderão então instalar todos os pacotes necessários com um install -r:
(tutorial-env) $ python -m pip install -r requirements.txt
Collecting novas==3.1.1.3 (from -r requirements.txt (line 1))
...
Collecting numpy==1.9.2 (from -r requirements.txt (line 2))
...
Collecting requests==2.7.0 (from -r requirements.txt (line 3))
...
(continua na próxima página)
pip tem inúmeras outras opções. Consulte o guia installing-index para a documentação completa do pip. Quando
você escrever um pacote e desejar deixá-lo disponível no Python Package Index, consulte o guia distributing-index.
E agora?
Ler este tutorial provavelmente reforçou seu interesse em usar Python — você deve estar ansioso para aplicar Python
para resolver problemas do mundo real. Aonde você deveria ir para aprender mais?
Este tutorial é parte do conjunto de documentação da linguagem Python. Alguns outros documentos neste conjunto
são:
• library-index:
Você deveria navegar através deste manual, que lhe dará material completo (ainda que breve) de referência
sobre tipos, funções e módulos na biblioteca padrão. A distribuição padrão do Python inclui muito código
adicional. Há módulos para ler caixa de correio Unix, baixar documentos via HTTP, gerar números aleatórios,
processar opções de linha de comando, escrever programas CGI, comprimir dados a muitas outras tarefas.
Uma lida rápida da Referência da Biblioteca lhe dará uma ideia do que está disponível.
• installing-index explica como instalar módulos adicionais escritos por outros usuários de Python.
• reference-index: Uma explicação detalhada da sintaxe e da semântica do Python. É uma leitura pesada, mas é
útil como um guia completo da linguagem propriamente dita.
Mais recursos Python:
• https://www.python.org: O principal website sobre Python. Ele contém código, documentação e aponta para
páginas na Web relacionadas ao Python. Esse site é espelhado em vários lugares do mundo como Europa, Japão
e Austrália; um espelho pode ser mais rápido que o site principal, dependendo da sua localização geográfica.
• https://docs.python.org: Acesso rápido à documentação Python.
• https://pypi.org: O índice de pacotes Python (Python package index), anteriormente apelidado de Cheese
Shop1 , é um índice de módulos Python criados pelos usuários. Uma vez que você começar a publicar código,
pode registrar seus pacotes aqui para que outros possam encontrá-los.
• https://code.activestate.com/recipes/langs/python/: O Python Cookbook (livro de receitas de Python) é uma
grande coleção de exemplos de código, módulos maiores e scripts úteis.Contribuições particularmente notáveis
são coletadas em um livro também chamado Python Cookbook (O’Reilly & Associates, ISBN 0-596-00797-3.)
• http://www.pyvideo.org contém links para vídeos relacionados a Python de conferências e encontros de grupos
de usuários.
1 “Cheese Shop” é o título de um quadro do grupo Monty Python: um freguês entra em uma loja especializada em queijos, mas qualquer queijo
que ele pede, o balconista diz que está em falta.
103
Python Tutorial, Release 3.9.1
• https://scipy.org: O projeto Scientific Python ( Python Científico) inclui módulos para computação e manipu-
lação rápida de vetores e também hospeda pacotes para coisas similares como álgebra linear, transformações
de Fourier, resolvedores não-lineares, distribuições de números aleatórios, análise estatística e afins.
Para reportar questões e problemas relacionadas a Python, você pode postar no newsgroup comp.lang.python ou
enviá-los para o grupo de e-mail em [email protected]. O newsgroup e a lista são conectados, então mensagens
postadas em um são automaticamente encaminhadas ao outro. Há centenas de postagem diárias perguntando (e
respondendo) perguntas, sugerindo novas funcionalidades e anunciando novos módulos. E-mails arquivados estão
disponíveis em https://mail.python.org/pipermail/. Existe também o grupo de discussão da comunidade brasileira de
Python: python-brasil no Google Groups (http://groups.google.com/group/python-brasil), com discussões de ótimo
nível técnico.
Antes de postar, certifique-se de checar a lista de Perguntas Frequentes (Frequently Asked Questions , também
chamada de FAQ). A FAQ responde muitas das perguntas que aparecem com frequência e pode já conter a solução
para o seu problema.
Notas de Rodapé
Algumas versões do interpretador Python suportam a edição da linha de entrada atual e a substituição da história,
semelhante às habilidade encontradas no shell Korn e no shell GNU Bash. Isso é implementado usando a biblioteca
GNU Readline, que oferece suporte a vários estilos de edição. Esta biblioteca possui sua própria documentação, que
não vamos duplicar aqui.
A conclusão dos nomes de variáveis e módulos é ativado automaticamente na inicialização do interpretador para que a
tecla :kbd:‘ Tab‘ invoque a função de conclusão. Ele analisa os nomes das instruções Python, as variáveis locais atuais
e os nomes dos módulos disponíveis. Para expressões pontilhadas como string.a, ele avaliará a expressão até o
'.' final e então sugerirá conclusões dos atributos do objeto resultante. Observe que isso pode executar o código
definido pelo aplicativo se um objeto com um método __getattr__() faz parte da expressão. A configuração
padrão também guarda seu histórico em um arquivo chamado .python_history no seu diretório de usuário. O
histórico estará disponível novamente durante a próxima sessão de interpretação interativa.
Esta facilidade é um enorme passo em frente em comparação com as versões anteriores do interpretador; No entanto,
alguns desejos são deixados: seria bom se a indentação adequada fosse sugerida nas linhas de continuação (o analisador
sabe se é necessário um token de recuo). O mecanismo de conclusão pode usar a tabela de símbolos do interpretador.
Um comando para verificar (ou mesmo sugerir) parênteses, citações, etc., também seria útil.
Um interpretador interativo aprimorado e alternativo que existe há algum tempo é o IPython, que apresenta a con-
clusão da guia, a exploração de objetos e o gerenciamento de histórico avançado. Também pode ser completamente
personalizado e incorporado em outras aplicações. Outro ambiente interativo aprimorado similar é bpython.
105
Python Tutorial, Release 3.9.1
Números de ponto flutuante são representados no hardware do computador como frações binárias (base 2). Por
exemplo, a fração decimal:
0.125
tem o valor 0/2 + 0/4 + 1/8. Essas duas frações têm valores idênticos, a única diferença real é que a primeira está
representada na forma de frações base 10, e a segunda na base 2.
Infelizmente, muitas frações decimais não podem ser representadas precisamente como frações binárias. O resultado
é que, em geral, os números decimais de ponto flutuante que você digita acabam sendo armazenados de forma apenas
aproximada, na forma de números binários de ponto flutuante.
O problema é mais fácil de entender primeiro em base 10. Considere a fração 1/3. Podemos representá-la aproxi-
madamente como uma fração base 10:
0.3
ou melhor,
0.33
ou melhor,
0.333
e assim por diante. Não importa quantos dígitos você está disposto a escrever, o resultado nunca será exatamente
1/3, mas será uma aproximação de cada vez melhor de 1/3.
Da mesma forma, não importa quantos dígitos de base 2 estejas disposto a usar, o valor decimal 0.1 não pode ser
representado exatamente como uma fração de base 2. No sistema de base 2, 1/10 é uma fração binária que se repete
infinitamente:
0.0001100110011001100110011001100110011001100110011...
Se parares em qualquer número finito de bits, obterás uma aproximação. Hoje em dia, na maioria dos computadores,
as casas decimais são aproximados usando uma fração binária onde o numerado utiliza os primeiros 53 bits iniciando
107
Python Tutorial, Release 3.9.1
no bit mais significativo e tendo como denominador uma potência de dois. No caso de 1/10, a fração binária seria
602879701896397 / 2 ** 55 o que chega bem perto, mas mesmo assim, não é igual ao valor original de
1/10.
É fácil esquecer que o valor armazenado é uma aproximação da fração decimal original, devido à forma como os
floats são exibidos no interpretador interativo. O Python exibe apenas uma aproximação decimal do verdadeiro valor
decimal da aproximação binária armazenada pela máquina. Se o Python exibisse o verdadeiro valor decimal da
aproximação binária que representa o decimal 0.1, seria necessário mostrar:
>>> 0.1
0.1000000000000000055511151231257827021181583404541015625
Contém muito mais dígitos do que é o esperado e utilizado pela grande maioria dos desenvolvedores, portanto, o
Python limita o número de dígitos exibidos, apresentando um valor arredondado, ao invés de mostrar todas as casas
decimais:
>>> 1 / 10
0.1
Lembre-se, mesmo que o resultado impresso seja o valor exato de 1/10, o valor que verdadeiramente estará armaze-
nado será uma fração binária representável que mais se aproxima.
Curiosamente, existem muitos números decimais diferentes que compartilham a mesma fra-
ção binária aproximada. Por exemplo, os números 0.1 ou o 0.10000000000000001 e 0.
1000000000000000055511151231257827021181583404541015625 são todos aproximações
de 3602879701896397/2 ** 55. Como todos esses valores decimais compartilham um mesma de
aproximação, qualquer um poderá ser exibido enquanto for preservado o invariante eval(repr(x)) == x.
Historicamente, o prompt do Python e a função embutida repr() utilizariam o que contivesse 17 dígitos significa-
tivos,“0.10000000000000001“. Desde a versão do Python 3.1, o Python (na maioria dos sistemas) agora é possível
optar pela forma mais reduzida, exibindo simplesmente o número 0.1.
Note que essa é a própria natureza do ponto flutuante binário: não é um bug do Python, e nem é um bug do seu código.
Essa situação pode ser observada em todas as linguagens que usam as instruções aritméticas de ponto flutuante do
hardware (apesar de algumas linguagens não mostrarem a diferença, por padrão, ou em todos os modos de saída).
Para obter um valor mais agradável, poderás utilizar a formatação de sequência de caracteres sendo capaz de gerar
um número limitado de dígitos significativos:
>>> repr(math.pi)
'3.141592653589793'
É importante perceber que tudo não passa de pura ilusão: estas simplesmente arredondando a exibição da verdadeira
maquinaria do valor.
Uma ilusão pode gerar outra. Por exemplo, uma vez que 0,1 não é exatamente 1/10, somar três vezes o valor 0.1,
não garantirá que o resultado seja exatamente 0,3, isso porque:
>>> .1 + .1 + .1 == .3
False
Inclusive, uma vez que o 0,1 não consegue aproximar-se do valor exato de 1/10 e 0,3 não pode se aproximar mais do
valor exato de 3/10, temos então que o pré-arredondamento com a função round() não servirá como ajuda:
Embora os números não possam se aproximar mais dos exatos valores que desejamos, a função round() poderá
ser útil na obtenção do pós-arredondamento para que os resultados contendo valores inexatos se tornem comparáveis
uns aos outros:
A aritmética de ponto flutuante binário traz muitas surpresas como essas. O problema do “0.1” é explicado em
detalhes precisos abaixo, na seção “Erro de Representação”. Para uma descrição mais completa de outras surpresas
que comumente nos deparamos, veja a seção The Perils of Floating Point que contém diversos exemplos distintos.
Como dizemos perto do final, “não há respostas fáceis”. Ainda assim, não se percam indevidamente no uso do ponto
flutuante! Os erros nas operações do tipo float do Python são heranças do hardware de ponto flutuante e, a maioria
dos computadores estão na ordem de não mais do que 1 parte em 2**53 por operação. Isso é mais do que o suficiente
para a maioria das tarefas, portanto, é importante lembrar que não se trata de uma aritmética decimal e que toda
operação com o tipo float poderá via a apresentar novos problemas referentes ao arredondamento.
Embora existam casos patológicos, na maior parte das vezes, terás como resultado final o valor esperado, se sim-
plesmente arredondares a exibição final dos resultados para a quantidade de dígitos decimais que esperas a função
str() geralmente será o suficiente, e , para seja necessário um valor refinado, veja os especificadores de formato
str.format() contido na seção formatstrings.
Para as situações que exijam uma representação decimal exata, experimente o módulo decimal que possui, a
implementação de uma adequada aritmética decimal bastante utilizada nas aplicações contábeis e pelas aplicações
que demandam alta precisão.
Uma outra forma de obter uma aritmética exata tem suporte pelo módulo fracções que implementa a aritmética
baseada em números racionais (portanto, os números fracionários como o 1/3 conseguem uma representação precisa).
Caso necessites fazer um intenso uso das operações de ponto flutuante, é importante que conheças o pacote Numerical
Python e, também é importante dizer, que existem diversos pacotes destinados ao trabalho intenso com operações
matemáticas e estatísticas que são fornecidas pelo projeto SciPy. Veja <https://scipy.org>.
O Python fornece ferramentas que podem ajudar nessas raras ocasiões em que realmente faz necessitas conhecer o
valor exato de um float. O método float.as_integer_ratio() expressa o valor do tipo float em sua forma
fracionária:
>>> x = 3.14159
>>> x.as_integer_ratio()
(3537115888337719, 1125899906842624)
Uma vez que a relação seja exata, será possível utiliza-la para obter, sem que haja quaisquer perda o valor original:
O método float.hex() expressa um tipo float em hexadecimal (base 16), o mesmo também conferirá o valor
exato pelo computador:
>>> x.hex()
'0x1.921f9f01b866ep+1'
Sua precisa representação hexadecimal poderá ser utilizada para reconstruir o valor exato do float:
>>> x == float.fromhex('0x1.921f9f01b866ep+1')
True
Como a representação será exata, é interessante utilizar valores confiáveis em diferentes versões do Python (inde-
pendente da plataforma) e a troca de dados entre idiomas diferentes que forneçam o mesmo formato (como o Java e
o C99).
Uma outra ferramenta que poderá ser útil é a função math.fsum() que ajuda a mitigar a perda de precisão durante
a soma. Ele rastreia “dígitos perdidos”, isso porque, os valores serão adicionados a um total em execução. Isso poderá
109
Python Tutorial, Release 3.9.1
fazer a diferença na precisão geral de forma que os erros não se acumulem chegando ao ponto de afetar o resultado
final:
Esta seção explica o exemplo do “0,1” em detalhes, e mostra como poderás realizar uma análise exata de casos
semelhantes. Assumimos que tenhas uma familiaridade básica com a representação binária de ponto flutuante.
Erro de representação refere-se ao fato de que algumas frações decimais (a maioria, na verdade) não podem ser
representadas exatamente como frações binárias (base 2). Esta é a principal razão por que o Python (ou Perl, C,
C++, Java, Fortran, e muitas outras) frequentemente não exibe o número decimal exato conforme o esperado:
Por que isso acontece? 1/10 e 2/10 não são podem ser representados exatamente sendo frações binárias. Atualmente,
quase todos computadores (julho de 2010) usam aritmética de ponto flutuante conforme a norma IEEE-754, e o
Python, em quase todas as plataformas, representa um float como um “IEEE-754 double precision float” (“float de
precisão dupla IEEE-754”). Os tais “doubles IEEE-754” têm 53 bits de precisão, por isso na entrada o computador
se esforça para converter “0.1” pra fração mais próxima que puder, na forma J/2**N onde J é um número inteiro
contendo exatamente 53 bits. Reescrevendo:
1 / 10 ~= J / (2**N)
como
J ~= 2**N / 10
e recordando que J tenha exatamente 53 bits (é >= 2**52, mas < 2**53), o melhor valor para N é 56:
Ou seja, 56 é o único valor de N que deixa J com exatamente 53 bits. Portanto, o melhor valor que conseguimos
obter pra J será aquele que possui o quociente arredondado:
Uma vez que o resto seja maior do que a metade de 10, a melhor aproximação que poderá ser obtida se arredondarmos
para cima:
>>> q+1
7205759403792794
7205759403792794 / 2 ** 56
3602879701896397 / 2 ** 55
Note que, como arredondamos para cima, esse valor é, de fato, um pouco maior que 1/10; se não tivéssemos ar-
redondado para cima, o quociente teria sido um pouco menor que 1/10. Mas em nenhum caso seria possível obter
exatamente o valor 1/10!
Por isso, o computador nunca “vê” 1/10: o que ele vê é exatamente a fração que é obtida pra cima, a melhor aproxi-
mação “IEEE-754 double” possível é:
>>> 0.1 * 2 ** 55
3602879701896397.0
Se multiplicarmos essa fração por 10**30, podemos ver o valor contendo os 55 dígitos mais significativos:
>>> 3602879701896397 * 10 ** 55 // 2 ** 55
1000000000000000055511151231257827021181583404541015625
o que significa que o número exato armazenados no computador será aproximadamente igual ao o valor decimal
0.100000000000000005551115123125. Versões do Python anteriores a 2.7 e a 3.1, esse valor era exibido pelo
arredondamento dos 17 dígitos significativos, produzindo ‘0.10000000000000001’. As últimas versões, o Python
está exibindo fração decimal mais curta que poderá ser convertida para o verdadeiro valor binário, o que resulta
simplesmente em ‘0.1’.
Módulos como o fractions e o decimal tornam esses cálculos muito mais fáceis:
>>> Fraction.from_float(0.1)
Fraction(3602879701896397, 36028797018963968)
>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)
>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
Anexo
Quando um erro ocorre, o interpretador exibe uma mensagem de erro e um stack trace (rastreamento de pilha). Se
estiver no modo interativo, ele volta para o prompt primário; se a entrada veio de um arquivo, a execução termina com
um status de saída nonzero (diferente de zero) após a exibição do stack trace. (Exceções tratadas por uma cláusula
except numa declaração try não são consideradas erros, nesse contexto.) Alguns erros são irremediavelmente
graves e causam términos de execução com status de saída nonzero; isso pode acontecer devido a inconsistências
internas e em alguns casos por falta de memória. Todas as mensagens de erro são escritas no fluxo de erros padrão;
a saída normal resultante da execução de comandos é escrita no canal de saída padrão.
Digitar o caractere de interrupção (geralmente Control-C ou Delete) em prompts primários ou secundários
causam a interrupção da entrada de dados e o retorno ao prompt primário.1 Digitar a interrupção durante a execução
de um comando levanta a exceção KeyboardInterrupt, que pode ser tratada por uma declaração try.
Em sistemas Unix similares ao BSD, scripts Python podem ser executados diretamente, tal como scripts shell, se
tiverem a linha de código
#!/usr/bin/env python3.5
(assumindo que o interpretador está na PATH do usuário) no começo do script e configurando o arquivo no modo
executável. Os dois primeiros caracteres do arquivo devem ser #!. Em algumas plataformas, essa primeira linha deve
terminar com uma quebra de linha em estilo Unix ('\n'), e não em estilo windows ('\r\n'). Note que o caractere
'#' (em inglês chamado de hash, ou pound etc.), é usado em Python para marcar o início de um comentário.
O script pode receber a permissão para atuar em modo executável através do comando chmod.
$ chmod +x myscript.py
1 Um problema com a package GNU Readline pode impedir que isso aconteça.
113
Python Tutorial, Release 3.9.1
Em sistemas Windows, não existe a noção de um “modo executável”. O instalador Python associa automaticamente
os arquivos .py com o python.exe, de forma que um clique duplo num arquivo Python o executará como um
script. A extensão pode ser também .pyw, o que omite a janela de console que normalmente aparece.
Quando se usa o Python no modo interativo, pode ser útil definir alguns comandos que sejam executados automati-
camente toda vez que o interpretador for inicializado. Isso pode ser feito configurando-se uma variável de ambiente
chamada PYTHONSTARTUP para que ela aponte para o arquivo contendo esses comandos. Isso é similar ao recurso
.profile das shells Unix.
Esse arquivo será lido apenas em sessões do modo interativo, e não quando Python lê comandos de um script, tam-
pouco quando /dev/tty é passado explicitamente como a origem dos comandos (neste caso, teremos um compor-
tamento similar a uma sessão interativa padrão). Ele é executado no mesmo namespace (espaço de nomes) em que
os comandos interativos são executados, de modo que os objetos que ele define ou importa possam ser usados sem
qualificação na sessão interativa. Também é possível alterar os prompts sys.ps1 e sys.ps2 no mesmo arquivo.
Caso deseje usar um arquivo de inicialização adicional a partir do atual diretório de trabalho, você pode programá-
lo no arquivo de inicialização global usando um código parecido com if os.path.isfile('.pythonrc.
py'): exec(open('.pythonrc.py').read()). Se quiser usar o arquivo de inicialização num script,
será necessário fazê-lo explicitamente no script:
import os
filename = os.environ.get('PYTHONSTARTUP')
if filename and os.path.isfile(filename):
with open(filename) as fobj:
startup_file = fobj.read()
exec(startup_file)
Python oferece dois hooks que permitem sua customização: sitecustomize e usercustomize. Para entender
como funcionam, primeiro você deve localizar o diretório site-packages do usuário. Inicie o Python e execute este
código:
Agora você pode criar um arquivo chamado usercustomize.py neste diretório e colocar qualquer coisa que
quiser dentro. Isto vai afetar toda invocação do Python, a menos que seja iniciado com a opção -s para desabilitar a
importação automática.
sitecustomize funciona da mesma forma, mas normalmente é criado por um administrador do computador no
diretório site-packages global e é importado antes de usercustomize. Veja a documentação do módulo site
para mais detalhes.
Notas de Rodapé
Glossário
>>> O prompt padrão do console interativo do Python. Normalmente visto em exemplos de código que podem ser
executados interativamente no interpretador.
... Pode se referir a:
• O prompt padrão do shell interativo do Python ao inserir o código para um bloco de código recuado,
quando dentro de um par de delimitadores correspondentes esquerdo e direito (parênteses, colchetes,
chaves ou aspas triplas) ou após especificar um decorador.
• A constante embutida Ellipsis.
2to3 Uma ferramenta que tenta converter código Python 2.x em código Python 3.x tratando a maioria das incom-
patibilidades que podem ser detectadas com análise do código-fonte e navegação na árvore sintática.
O 2to3 está disponível na biblioteca padrão como lib2to3; um ponto de entrada é disponibilizado como
Tools/scripts/2to3. Veja 2to3-reference.
classe base abstrata Classes bases abstratas complementam tipagem pato, fornecendo uma maneira de definir in-
terfaces quando outras técnicas, como hasattr(), seriam desajeitadas ou sutilmente erradas (por exemplo,
com métodos mágicos). ABCs introduzem subclasses virtuais, classes que não herdam de uma classe mas
ainda são reconhecidas por isinstance() e issubclass(); veja a documentação do módulo abc.
Python vem com muitas ABCs embutidas para estruturas de dados (no módulo collections.abc), nú-
meros (no módulo numbers), fluxos (no módulo io), localizadores e carregadores de importação (no módulo
importlib.abc). Você pode criar suas próprias ABCs com o módulo abc.
anotação Um rótulo associado a uma variável, um atributo de classe ou um parâmetro de função ou valor de retorno,
usado por convenção como dica de tipo.
Anotações de variáveis locais não podem ser acessadas em tempo de execução, mas anotações de variáveis
globais, atributos de classe e funções são armazenadas no atributo especial __annotations__ de módulos,
classes e funções, respectivamente.
Veja anotação de variável, anotação de função, PEP 484 e PEP 526, que descrevem esta funcionalidade.
argumento Um valor passado para uma função (ou método) ao chamar a função. Existem dois tipos de argumento:
• argumento nomeado: um argumento precedido por um identificador (por exemplo, name=) na chamada
de uma função ou passada como um valor em um dicionário precedido por **. Por exemplo, 3 e 5 são
ambos argumentos nomeados na chamada da função complex() a seguir:
complex(real=3, imag=5)
complex(**{'real': 3, 'imag': 5})
115
Python Tutorial, Release 3.9.1
• argumento posicional: um argumento que não é um argumento nomeado. Argumentos posicionais po-
dem aparecer no início da lista de argumentos e/ou podem ser passados com elementos de um iterável
precedido por *. Por exemplo, 3 e 5 são ambos argumentos posicionais nas chamadas a seguir:
complex(3, 5)
complex(*(3, 5))
Argumentos são atribuídos às variáveis locais nomeadas no corpo da função. Veja a seção calls para as regras
de atribuição. Sintaticamente, qualquer expressão pode ser usada para representar um argumento; avaliada a
expressão, o valor é atribuído à variável local.
Veja também o termo parâmetro no glossário, a pergunta no FAQ sobre a diferença entre argumentos e parâ-
metros e PEP 362.
gerenciador de contexto assíncrono Um objeto que controla o ambiente visto numa instrução async with por
meio da definição dos métodos __aenter__() e __aexit__(). Introduzido pela PEP 492.
gerador assíncrono Uma função que retorna um iterador gerador assíncrono. É parecida com uma função de cor-
rotina definida com async def exceto pelo fato de conter instruções yield para produzir uma série de
valores que podem ser usados em um laço async for.
Normalmente se refere a uma função geradora assíncrona, mas pode se referir a um iterador gerador assín-
crono em alguns contextos. Em casos em que o significado não esteja claro, usar o termo completo evita a
ambiguidade.
Uma função geradora assíncrona pode conter expressões await e também as instruções async for e
async with.
iterador gerador assíncrono Um objeto criado por uma função geradora assíncrona.
Este é um iterador assíncrono que, quando chamado usando o método __anext__(), retorna um objeto
aguardável que executará o corpo da função geradora assíncrona até a próxima expressão yield.
Cada yield suspende temporariamente o processamento, lembrando o estado de execução do local (incluindo
variáveis locais e instruções try pendentes). Quando o iterador gerador assíncrono efetivamente é retomado
com outro aguardável retornado por __anext__(), ele inicia de onde parou. Veja PEP 492 e PEP 525.
iterável assíncrono Um objeto que pode ser usado em uma instrução async for. Deve retornar um iterador
assíncrono do seu método __aiter__(). Introduzido por PEP 492.
iterador assíncrono Um objeto que implementa os métodos __aiter__() e __anext__(). __anext__
deve retornar um objeto aguardável. async for resolve os aguardáveis retornados por um método
__anext__() do iterador assíncrono até que ele levante uma exceção StopAsyncIteration. Intro-
duzido pela PEP 492.
atributo Um valor associado a um objeto que é referenciado pelo nome separado por um ponto. Por exemplo, se
um objeto o tem um atributo a esse seria referenciado como o.a.
aguardável Um objeto que pode ser usado em uma expressão await. Pode ser uma corrotina ou um objeto com
um método __await__(). Veja também a PEP 492.
BDFL Abreviação da expressão da língua inglesa “Benevolent Dictator for Life” (em português, “Ditador Benevo-
lente Vitalício”), referindo-se a Guido van Rossum, criador do Python.
arquivo binário Um objeto arquivo capaz de ler e gravar em objetos byte ou similar. Exemplos de arquivos binários
são arquivos abertos no modo binário ('rb', 'wb' ou 'rb+'), sys.stdin.buffer, sys.stdout.
buffer e instâncias de io.BytesIO e gzip.GzipFile.
Veja também arquivo texto para um objeto arquivo capaz de ler e gravar em objetos str.
objeto byte ou similar Um objeto com suporte ao o bufferobjects e que pode exportar um buffer C contíguo. Isso
inclui todos os objetos bytes, bytearray e array.array, além de muitos objetos memoryview co-
muns. Objetos byte ou similar podem ser usados para várias operações que funcionam com dados binários;
isso inclui compactação, salvamento em um arquivo binário e envio por um soquete.
Algumas operações precisam que os dados binários sejam mutáveis. A documentação geralmente se refere
a eles como “objetos byte ou similar para leitura e escrita”. Exemplos de objetos de buffer mutável incluem
117
Python Tutorial, Release 3.9.1
decorador Uma função que retorna outra função, geralmente aplicada como uma transformação de função usando
a sintaxe @wrapper. Exemplos comuns para decoradores são classmethod() e staticmethod().
A sintaxe do decorador é meramente um açúcar sintático, as duas definições de funções a seguir são semanti-
camente equivalentes:
def f(...):
...
f = staticmethod(f)
@staticmethod
def f(...):
...
O mesmo conceito existe para as classes, mas não é comumente utilizado. Veja a documentação de definições
de função e definições de classe para obter mais informações sobre decoradores.
descritor Qualquer objeto que define os métodos __get__(), __set__() ou __delete__(). Quando um
atributo de classe é um descritor, seu comportamento de associação especial é acionado no acesso a um atributo.
Normalmente, ao se utilizar a.b para se obter, definir ou excluir, um atributo dispara uma busca no objeto
chamado b no dicionário de classe de a, mas se b for um descritor, o respectivo método descritor é chamado.
Compreender descritores é a chave para um profundo entendimento de Python pois eles são a base de muitas
funcionalidades incluindo funções, métodos, propriedades, métodos de classe, métodos estáticos e referências
para superclasses.
Para obter mais informações sobre os métodos dos descritores, veja: descriptors ou o Guia de Descritores.
dicionário Um vetor associativo em que chaves arbitrárias são mapeadas para valores. As chaves podem ser quais-
quer objetos que possuam os métodos __hash__() e __eq__(). Dicionários são estruturas chamadas de
hash na linguagem Perl.
compreensão de dicionário Uma maneira compacta de processar todos ou parte dos elementos de um iterável e
retornar um dicionário com os resultados. results = {n: n ** 2 for n in range(10)} gera
um dicionário contendo a chave n mapeada para o valor n ** 2. Veja comprehensions.
visão de dicionário Os objetos retornados por dict.keys(), dict.values() e dict.items() são cha-
mados de visões de dicionário. Eles fornecem uma visão dinâmica das entradas do dicionário, o que significa
que quando o dicionário é alterado, a visão reflete essas alterações. Para forçar a visão de dicionário a se tornar
uma lista completa use list(dictview). Veja dict-views.
docstring Abreviatura de “documentation string” (string de documentação). Uma string literal que aparece como
primeira expressão numa classe, função ou módulo. Ainda que sejam ignoradas quando a suíte é executada, é
reconhecida pelo compilador que a coloca no atributo __doc__ da classe, função ou módulo que a encapsula.
Como ficam disponíveis por meio de introspecção, docstrings são o lugar canônico para documentação do
objeto.
tipagem pato Também conhecida como duck-typing, é um estilo de programação que não verifica o tipo do objeto
para determinar se ele possui a interface correta; em vez disso, o método ou atributo é simplesmente chamado
ou utilizado (“Se se parece com um pato e grasna como um pato, então deve ser um pato.”) Enfatizando
interfaces ao invés de tipos específicos, o código bem desenvolvido aprimora sua flexibilidade por permitir
substituição polimórfica. Tipagem pato evita necessidade de testes que usem type() ou isinstance().
(Note, porém, que a tipagem pato pode ser complementada com o uso de classes base abstratas.) Ao invés
disso, são normalmente empregados testes hasattr() ou programação EAFP.
EAFP Iniciais da expressão em inglês “easier to ask for forgiveness than permission” que significa “é mais fácil
pedir perdão que permissão”. Este estilo de codificação comum em Python assume a existência de chaves ou
atributos válidos e captura exceções caso essa premissa se prove falsa. Este estilo limpo e rápido se caracteriza
pela presença de várias instruções try e except. A técnica diverge do estilo LBYL, comum em outras
linguagens como C, por exemplo.
expressão Uma parte da sintaxe que pode ser avaliada para algum valor. Em outras palavras, uma expressão é a
acumulação de elementos de expressão como literais, nomes, atributos de acesso, operadores ou chamadas
de funções, todos os quais retornam um valor. Em contraste com muitas outras linguagens, nem todas as
construções de linguagem são expressões. Também existem instruções, as quais não podem ser usadas como
expressões, como, por exemplo, while. Atribuições também são instruções, não expressões.
módulo de extensão Um módulo escrito em C ou C++, usando a API C do Python para interagir tanto com código
de usuário quanto do núcleo.
f-string Literais string prefixadas com 'f' ou 'F' são conhecidas como “f-strings” que é uma abreviação de
formatted string literals. Veja também PEP 498.
objeto arquivo Um objeto que expõe uma API orientada a arquivos (com métodos tais como read() ou
write()) para um recurso subjacente. Dependendo da maneira como foi criado, um objeto arquivo pode
mediar o acesso a um arquivo real no disco ou outro tipo de dispositivo de armazenamento ou de comunicação
(por exemplo a entrada/saída padrão, buffers em memória, soquetes, pipes, etc.). Objetos arquivo também
são chamados de objetos arquivo ou similares ou fluxos.
Atualmente há três categorias de objetos arquivo: arquivos binários brutos, arquivos binários em buffer e
arquivos textos. Suas interfaces estão definidas no módulo io. A forma canônica para criar um objeto arquivo
é usando a função open().
objeto arquivo ou similar Um sinônimo do termo objeto arquivo.
localizador Um objeto que tenta encontrar o carregador para um módulo que está sendo importado.
Desde o Python 3.3, existem dois tipos de localizador: localizadores de metacaminho para uso com sys.
meta_path, e localizadores de entrada de caminho para uso com sys.path_hooks.
Veja PEP 302, PEP 420 e PEP 451 para mais informações.
divisão pelo piso Divisão matemática que arredonda para baixo para o inteiro mais próximo. O operador de divisão
pelo piso é //. Por exemplo, a expressão 11 // 4 retorna o valor 2 ao invés de 2.75, que seria retornado
pela divisão de ponto flutuante. Note que (-11) // 4 é -3 porque é -2.75 arredondado para baixo.
Consulte a PEP 238.
função Uma série de instruções que retorna algum valor para um chamador. Também pode ser passado zero ou mais
argumentos que podem ser usados na execução do corpo. Veja também parâmetro, método e a seção function.
anotação de função Uma anotação de um parâmetro de função ou valor de retorno.
Anotações de função são comumente usados por dicas de tipo: por exemplo, essa função espera receber dois
argumentos int e também é esperado que devolva um valor int:
coleta de lixo Também conhecido como garbage collection, é o processo de liberar a memória quando ela não é
mais utilizada. Python executa a liberação da memória através da contagem de referências e um coletor de lixo
cíclico que é capaz de detectar e interromper referências cíclicas. O coletor de lixo pode ser controlado usando
o módulo gc.
gerador Uma função que retorna um iterador gerador. É parecida com uma função normal, exceto pelo fato de
conter expressões yield para produzir uma série de valores que podem ser usados em um laço “for” ou que
podem ser obtidos um de cada vez com a função next().
119
Python Tutorial, Release 3.9.1
Normalmente refere-se a uma função geradora, mas pode referir-se a um iterador gerador em alguns contextos.
Em alguns casos onde o significado desejado não está claro, usar o termo completo evita ambiguidade.
iterador gerador Um objeto criado por uma função geradora.
Cada yield suspende temporariamente o processamento, memorizando o estado da execução local (incluindo
variáveis locais e instruções try pendentes). Quando o iterador gerador retorna, ele se recupera do último ponto
onde estava (em contrapartida as funções que iniciam uma nova execução a cada vez que são invocadas).
expressão geradora Uma expressão que retorna um iterador. Parece uma expressão normal, seguido de uma cláu-
sula for definindo uma variável de loop, um range, e uma cláusula if opcional. A expressão combinada gera
valores para uma função encapsuladora:
função genérica Uma função composta por várias funções implementando a mesma operação para diferentes tipos.
Qual implementação deverá ser usada durante a execução é determinada pelo algoritmo de despacho.
Veja também a entrada despacho único no glossário, o decorador functools.singledispatch(), e a
PEP 443.
tipo genérico Um tipo que pode ser parametrizado; tipicamente um contêiner como list. Usado para dicas de tipo
e anotações.
Veja PEP 483 para mais detalhes e typing ou tipo de alias genérico para seus usuários.
GIL Veja bloqueio global do interpretador.
bloqueio global do interpretador O mecanismo utilizado pelo interpretador CPython para garantir que apenas uma
thread execute o bytecode Python por vez. Isto simplifica a implementação do CPython ao fazer com que o
modelo de objetos (incluindo tipos embutidos críticos como o dict) ganhem segurança implícita contra acesso
concorrente. Travar todo o interpretador facilita que o interpretador em si seja multitarefa, às custas de muito
do paralelismo já provido por máquinas multiprocessador.
No entanto, alguns módulos de extensão, tanto da biblioteca padrão quanto de terceiros, são desenvolvidos de
forma a liberar o GIL ao realizar tarefas computacionalmente muito intensas, como compactação ou cálculos
de hash. Além disso, o GIL é sempre liberado nas operações de E/S.
No passado, esforços para criar um interpretador que lidasse plenamente com threads (travando dados com-
partilhados numa granularidade bem mais fina) não foram bem sucedidos devido a queda no desempenho ao
serem executados em processadores de apenas um núcleo. Acredita-se que superar essa questão de desempe-
nho acabaria tornando a implementação muito mais complicada e bem mais difícil de manter.
pyc baseado em hash Um arquivo de cache em bytecode que usa hash ao invés do tempo, no qual o arquivo de
código-fonte foi modificado pela última vez, para determinar a sua validade. Veja pyc-invalidation.
hasheável Um objeto é hasheável se tem um valor de hash que nunca muda durante seu ciclo de vida (precisa ter
um método __hash__()) e pode ser comparado com outros objetos (precisa ter um método __eq__()).
Objetos hasheáveis que são comparados como iguais devem ter o mesmo valor de hash.
A hasheabilidade faz com que um objeto possa ser usado como uma chave de dicionário e como um membro
de conjunto, pois estas estruturas de dados utilizam os valores de hash internamente.
A maioria dos objetos embutidos imutáveis do Python são hasheáveis; containers mutáveis (tais como listas
ou dicionários) não são; containers imutáveis (tais como tuplas e frozensets) são hasheáveis apenas se os seus
elementos são hasheáveis. Objetos que são instâncias de classes definidas pelo usuário são hasheáveis por
padrão. Todos eles comparam de forma desigual (exceto entre si mesmos), e o seu valor hash é derivado a
partir do seu id().
IDLE Um ambiente de desenvolvimento integrado para Python. IDLE é um editor básico e um ambiente interpre-
tador que vem junto com a distribuição padrão do Python.
imutável Um objeto que possui um valor fixo. Objetos imutáveis incluem números, strings e tuplas. Estes objetos
não podem ser alterados. Um novo objeto deve ser criado se um valor diferente tiver de ser armazenado.
Objetos imutáveis têm um papel importante em lugares onde um valor constante de hash seja necessário, como
por exemplo uma chave em um dicionário.
caminho de importação Uma lista de localizações (ou entradas de caminho) que são buscadas pelo localizador
baseado no caminho por módulos para importar. Durante a importação, esta lista de localizações usualmente
vem a partir de sys.path, mas para subpacotes ela também pode vir do atributo __path__ de pacotes-pai.
importação O processo pelo qual o código Python em um módulo é disponibilizado para o código Python em outro
módulo.
importador Um objeto que localiza e carrega um módulo; Tanto um localizador e o objeto carregador.
interativo Python tem um interpretador interativo, o que significa que você pode digitar instruções e expressões
no prompt do interpretador, executá-los imediatamente e ver seus resultados. Apenas execute python sem
argumentos (possivelmente selecionando-o a partir do menu de aplicações de seu sistema operacional). O
interpretador interativo é uma maneira poderosa de testar novas ideias ou aprender mais sobre módulos e
pacotes (lembre-se do comando help(x)).
interpretado Python é uma linguagem interpretada, em oposição àquelas que são compiladas, embora esta distinção
possa ser nebulosa devido à presença do compilador de bytecode. Isto significa que os arquivos-fontes podem
ser executados diretamente sem necessidade explícita de se criar um arquivo executável. Linguagens inter-
pretadas normalmente têm um ciclo de desenvolvimento/depuração mais curto que as linguagens compiladas,
apesar de seus programas geralmente serem executados mais lentamente. Veja também interativo.
desligamento do interpretador Quando solicitado para desligar, o interpretador Python entra em uma fase espe-
cial, onde ele gradualmente libera todos os recursos alocados, tais como módulos e várias estruturas internas
críticas. Ele também faz diversas chamadas para o coletor de lixo. Isto pode disparar a execução de código
em destrutores definidos pelo usuário ou função de retorno de referência fraca. Código executado durante a
fase de desligamento pode encontrar diversas exceções, pois os recursos que ele depende podem não funcionar
mais (exemplos comuns são os módulos de bibliotecas, ou os mecanismos de avisos).
A principal razão para o interpretador desligar, é que o módulo __main__ ou o script sendo executado
terminou sua execução.
iterável Um objeto capaz de retornar seus membros um de cada vez. Exemplos de iteráveis incluem todos os tipos de
sequência (tais como list, str e tuple) e alguns tipos não sequenciais como dict, objeto arquivo, e obje-
tos de qualquer classe que você definir com um método __iter__() ou com um método __getitem__()
que implemente a semântica de Sequência.
Iteráveis podem ser usados em um laço for e em vários outros lugares em que uma sequência é necessária
(zip(), map(), …). Quando um objeto iterável é passado como argumento para a função nativa iter(),
ela retorna um iterador para o objeto. Este iterador é adequado para se varrer todo o conjunto de valores. Ao
usar iteráveis, normalmente não é necessário chamar iter() ou lidar com os objetos iteradores em si. A
instrução for faz isso automaticamente para você, criando uma variável temporária para armazenar o iterador
durante a execução do laço. Veja também iterador, sequência, e gerador.
iterador Um objeto que representa um fluxo de dados. Repetidas chamadas ao método __next__() de um
iterador (ou passando o objeto para a função embutida next()) vão retornar itens sucessivos do fluxo. Quando
não houver mais dados disponíveis uma exceção StopIteration exception será levantada. Neste ponto, o
objeto iterador se esgotou e quaisquer chamadas subsequentes a seu método __next__() vão apenas levantar
a exceção StopIteration novamente. Iteradores precisam ter um método __iter__() que retorne o
objeto iterador em si, de forma que todo iterador também é iterável e pode ser usado na maioria dos lugares em
que um iterável é requerido. Uma notável exceção é código que tenta realizar passagens em múltiplas iterações.
Um objeto contêiner (como uma list) produz um novo iterador a cada vez que você passá-lo para a função
iter() ou utilizá-lo em um laço for. Tentar isso com o mesmo iterador apenas iria retornar o mesmo objeto
iterador esgotado já utilizado na iteração anterior, como se fosse um contêiner vazio.
Mais informações podem ser encontradas em typeiter.
função chave Uma função chave ou função colação é um chamável que retorna um valor usado para ordenação ou
classificação. Por exemplo, locale.strxfrm() é usada para produzir uma chave de ordenação que leva
o locale em consideração para fins de ordenação.
Uma porção de ferramentas em Python aceitam funções chave para controlar como os elementos são ordenados
ou agrupados. Algumas delas incluem min(), max(), sorted(), list.sort(), heapq.merge(),
121
Python Tutorial, Release 3.9.1
módulo Um objeto que serve como uma unidade organizacional de código Python. Os módulos têm um espaço de
nomes contendo objetos Python arbitrários. Os módulos são carregados pelo Python através do processo de
importação.
Veja também pacote.
módulo spec Um espaço de nomes que contém as informações relacionadas à importação usadas para carregar um
módulo. Uma instância de importlib.machinery.ModuleSpec.
MRO Veja ordem de resolução de métodos.
mutável Objeto mutável é aquele que pode modificar seus valor mas manter seu id(). Veja também imutável.
tupla nomeada O termo “tupla nomeada” é aplicado a qualquer tipo ou classe que herda de tupla e cujos elementos
indexáveis também são acessíveis usando atributos nomeados. O tipo ou classe pode ter outras funcionalidades
também.
Diversos tipos embutidos são tuplas nomeadas, incluindo os valores retornados por time.localtime() e
os.stat(). Outro exemplo é sys.float_info:
Algumas tuplas nomeadas são tipos embutidos (tal como os exemplos acima). Alternativamente, uma tupla
nomeada pode ser criada a partir de uma definição de classe regular, que herde de tuple e que defina campos
nomeados. Tal classe pode ser escrita a mão, ou ela pode ser criada com uma função fábrica collections.
namedtuple(). A segunda técnica também adiciona alguns métodos extras, que podem não ser encontrados
quando foi escrita manualmente, ou em tuplas nomeadas embutidas.
espaço de nomes O lugar em que uma variável é armazenada. Espaços de nomes são implementados como dicioná-
rios. Existem os espaços de nomes local, global e nativo, bem como espaços de nomes aninhados em objetos
(em métodos). Espaços de nomes suportam modularidade ao prevenir conflitos de nomes. Por exemplo, as
funções __builtin__.open() e os.open() são diferenciadas por seus espaços de nomes. Espaços
de nomes também auxiliam na legibilidade e na manutenibilidade ao torar mais claro quais módulos imple-
mentam uma função. Escrever random.seed() ou itertools.izip(), por exemplo, deixa claro que
estas funções são implementadas pelos módulos random e itertools respectivamente.
pacote de espaço de nomes Um pacote da PEP 420 que serve apenas como container para sub pacotes. Pacotes
de espaços de nomes podem não ter representação física, e especificamente não são como um pacote regular
porque eles não tem um arquivo __init__.py.
Veja também módulo.
escopo aninhado A habilidade de referir-se a uma variável em uma definição de fechamento. Por exemplo, uma
função definida dentro de outra pode referenciar variáveis da função externa. Perceba que escopos aninhados
por padrão funcionam apenas por referência e não por atribuição. Variáveis locais podem ler e escrever no
escopo mais interno. De forma similar, variáveis globais podem ler e escrever para o espaço de nomes global.
O nonlocal permite escrita para escopos externos.
classe estilo novo Antigo nome para o tipo de classes agora usado para todos os objetos de classes. Em versões
anteriores do Python, apenas classes estilo podiam usar recursos novos e versáteis do Python, tais como
__slots__, descritores, propriedades, __getattribute__(), métodos de classe, e métodos estáticos.
objeto Qualquer dado que tenha estado (atributos ou valores) e comportamento definidos (métodos). Também a
última classe base de qualquer classe estilo novo.
pacote Um módulo Python é capaz de conter submódulos ou recursivamente, subpacotes. Tecnicamente, um pacote
é um módulo Python com um atributo __path__.
Veja também pacote regular e pacote de espaço de nomes.
123
Python Tutorial, Release 3.9.1
parâmetro Uma entidade nomeada na definição de uma função (ou método) que específica um argumento (ou em
alguns casos, argumentos) que a função pode receber. Existem cinco tipos de parâmetros:
• posicional-ou-nomeado: especifica um argumento que pode ser tanto posicional quanto nomeado. Esse é
o tipo padrão de parâmetro, por exemplo foo e bar a seguir:
• somente-posicional: especifica um argumento que pode ser fornecido apenas por posição. Parâmetros
somente-posicionais podem ser definidos incluindo o caractere / na lista de parâmetros da definição da
função após eles, por exemplo posonly1 e posonly2 a seguir:
• somente-nomeado: especifica um argumento que pode ser passado para a função somente por nome.
Parâmetros somente-nomeados podem ser definidos com um simples parâmetro var-posicional ou um *
antes deles na lista de parâmetros na definição da função, por exemplo kw_only1 and kw_only2 a seguir:
• var-posicional: especifica que uma sequência arbitrária de argumentos posicionais pode ser fornecida
(em adição a qualquer argumento posicional já aceito por outros parâmetros). Tal parâmetro pode ser
definido colocando um * antes do nome do parâmetro, por exemplo args a seguir:
• var-nomeado: especifica que, arbitrariamente, muitos argumentos nomeados podem ser fornecidos (em
adição a qualquer argumento nomeado já aceito por outros parâmetros). Tal parâmetro pode definido
colocando-se ** antes do nome, por exemplo kwargs no exemplo acima.
Parâmetros podem especificar tanto argumentos opcionais quanto obrigatórios, assim como valores padrão
para alguns argumentos opcionais.
Veja o termo argumento no glossário, a pergunta sobre a diferença entre argumentos e parâmetros, a classe
inspect.Parameter, a seção function e a PEP 362.
entrada de caminho Um local único no caminho de importação que o localizador baseado no caminho consulta
para encontrar módulos a serem importados.
localizador de entrada de caminho Um localizador retornado por um chamável em sys.path_hooks (ou seja,
um gancho de entrada de caminho) que sabe como localizar os módulos entrada de caminho.
Veja importlib.abc.PathEntryFinder para os métodos que localizadores de entrada de caminho
implementam.
gancho de entrada de caminho Um chamável na lista sys.path_hook que retorna um localizador de entrada
de caminho caso saiba como localizar módulos em uma entrada de caminho específica.
localizador baseado no caminho Um dos localizadores de metacaminho que procura por um caminho de importa-
ção de módulos.
objeto caminho ou similar Um objeto representando um caminho de sistema de arquivos. Um objeto caminho ou
similar é ou um objeto str ou bytes representando um caminho, ou um objeto implementando o protocolo
os.PathLike. Um objeto que suporta o protocolo os.PathLike pode ser convertido para um arquivo
de caminho do sistema str ou bytes, através da chamada da função os.fspath(); os.fsdecode()
e os.fsencode() podem ser usadas para garantir um str ou bytes como resultado, respectivamente.
Introduzido na PEP 519.
PEP Proposta de melhoria do Python. Uma PEP é um documento de design que fornece informação para a co-
munidade Python, ou descreve uma nova funcionalidade para o Python ou seus predecessores ou ambientes.
PEPs devem prover uma especificação técnica concisa e um racional para funcionalidades propostas.
PEPs têm a intenção de ser os mecanismos primários para propor novas funcionalidades significativas, para
coletar opiniões da comunidade sobre um problema, e para documentar as decisões de design que foram adicio-
nadas ao Python. O autor da PEP é responsável por construir um consenso dentro da comunidade e documentar
opiniões dissidentes.
Veja PEP 1.
porção Um conjunto de arquivos em um único diretório (possivelmente armazenado em um arquivo zip) que con-
tribuem para um pacote de espaço de nomes, conforme definido em PEP 420.
argumento posicional Veja argumento.
API provisória Uma API provisória é uma API que foi deliberadamente excluída das bibliotecas padrões com com-
patibilidade retroativa garantida. Enquanto mudanças maiores para tais interfaces não são esperadas, contanto
que elas sejam marcadas como provisórias, mudanças retroativas incompatíveis (até e incluindo a remoção da
interface) podem ocorrer se consideradas necessárias pelos desenvolvedores principais. Tais mudanças não se-
rão feitas gratuitamente – elas irão ocorrer apenas se sérias falhas fundamentais forem descobertas, que foram
esquecidas anteriormente a inclusão da API.
Mesmo para APIs provisórias, mudanças retroativas incompatíveis são vistas como uma “solução em último
caso” - cada tentativa ainda será feita para encontrar uma resolução retroativa compatível para quaisquer pro-
blemas encontrados.
Esse processo permite que a biblioteca padrão continue a evoluir com o passar do tempo, sem se prender em
erros de design problemáticos por períodos de tempo prolongados. Veja PEP 411 para mais detalhes.
pacote provisório Veja API provisória.
Python 3000 Apelido para a linha de lançamento da versão do Python 3.x (cunhada há muito tempo, quando o
lançamento da versão 3 era algo em um futuro muito distante.) Esse termo possui a seguinte abreviação:
“Py3k”.
Pythônico Uma ideia ou um pedaço de código que segue de perto os idiomas mais comuns da linguagem Python,
ao invés de implementar códigos usando conceitos comuns a outros idiomas. Por exemplo, um idioma comum
em Python é fazer um loop sobre todos os elementos de uma iterável usando a instrução for. Muitas outras
linguagens não têm esse tipo de construção, então as pessoas que não estão familiarizadas com o Python usam
um contador numérico:
for i in range(len(food)):
print(food[i])
nome qualificado Um nome pontilhado (quando 2 termos são ligados por um ponto) que mostra o “path” do escopo
global de um módulo para uma classe, função ou método definido num determinado módulo, conforme definido
pela PEP 3155. Para funções e classes de nível superior, o nome qualificado é o mesmo que o nome do objeto:
>>> class C:
... class D:
... def meth(self):
... pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'
Quando usado para se referir a módulos, o nome totalmente qualificado significa todo o caminho pontilhado
para o módulo, incluindo quaisquer pacotes pai, por exemplo: email.mime.text:
125
Python Tutorial, Release 3.9.1
contagem de referências O número de referências para um objeto. Quando a contagem de referências de um objeto
atinge zero, ele é desalocado. Contagem de referências geralmente não é visível no código Python, mas é
um elemento chave da implementação CPython. O módulo sys define a função getrefcount() que
programadores podem chamar para retornar a contagem de referências para um objeto em particular.
pacote regular Um pacote tradicional, como um diretório contendo um arquivo __init__.py.
Veja também pacote de espaço de nomes.
__slots__ Uma declaração dentro de uma classe que economiza memória pré-declarando espaço para atributos de
instâncias, e eliminando dicionários de instâncias. Apesar de popular, a técnica é um tanto quanto complicada
de acertar, e é melhor se for reservada para casos raros, onde existe uma grande quantidade de instâncias em
uma aplicação onde a memória é crítica.
sequência Um iterável com suporte para acesso eficiente a seus elementos através de índices inteiros via método
especial __getitem__() e que define o método __len__() que devolve o tamanho da sequência. Alguns
tipos de sequência embutidos são: list, str, tuple, e bytes. Note que dict também tem suporte para
__getitem__() e __len__(), mas é considerado um mapa e não uma sequência porque a busca usa
uma chave imutável arbitrária em vez de inteiros.
A classe base abstrata collections.abc.Sequence define uma interface mais rica que vai além de
apenas __getitem__() e __len__(), adicionando count(), index(), __contains__(), e
__reversed__(). Tipos que implementam essa interface podem ser explicitamente registrados usando
register().
compreensão de conjunto Uma maneira compacta de processar todos ou parte dos elementos em iterável e retor-
nar um conjunto com os resultados. results = {c for c in 'abracadabra' if c not in
'abc'} gera um conjunto de strings {'r', 'd'}. Veja comprehensions.
despacho único Uma forma de despacho de função genérica onde a implementação é escolhida com base no tipo
de um único argumento.
fatia Um objeto geralmente contendo uma parte de uma sequência. Uma fatia é criada usando a notação de subscrito
[] pode conter também até dois pontos entre números, como em variable_name[1:3:5]. A notação
de suporte (subscrito) utiliza objetos slice internamente.
método especial Um método que é chamado implicitamente pelo Python para executar uma certa operação em um
tipo, como uma adição por exemplo. Tais métodos tem nomes iniciando e terminando com dois underscores.
Métodos especiais estão documentados em specialnames.
instrução Uma instrução é parte de uma suíte (um “bloco” de código). Uma instrução é ou uma expressão ou uma
de várias construções com uma palavra reservada, tal como if, while ou for.
codificador de texto Um codec que codifica strings Unicode para bytes.
arquivo texto Um objeto arquivo apto a ler e escrever objetos str. Geralmente, um arquivo texto, na verdade,
acessa um fluxo de dados de bytes e captura o codificador de texto automaticamente. Exemplos de arquivos
texto são: arquivos abertos em modo texto ('r' or 'w'), sys.stdin, sys.stdout, e instâncias de
io.StringIO.
Veja também arquivo binário para um objeto arquivo apto a ler e escrever objetos byte ou similar.
aspas triplas Uma string que está definida com três ocorrências de aspas duplas (“) ou apóstrofos (‘). Enquanto
elas não fornecem nenhuma funcionalidade não disponível com strings de aspas simples, elas são úteis para
inúmeras razões. Elas permitem que você inclua aspas simples e duplas não escapadas dentro de uma string,
e elas podem utilizar múltiplas linhas sem o uso de caractere de continuação, fazendo-as especialmente úteis
quando escrevemos documentação em docstrings.
tipo O tipo de um objeto Python determina qual tipo de objeto ele é; cada objeto tem um tipo. Um tipo de objeto é
acessível pelo atributo __class__ ou pode ser recuperado com type(obj).
tipo alias Um sinônimo para um tipo, criado através da atribuição do tipo para um identificador.
Tipos alias são úteis para simplificar dicas de tipo. Por exemplo:
def remove_gray_shades(
colors: list[tuple[int, int, int]]) -> list[tuple[int, int, int]]:
pass
class C:
field: 'annotation'
Anotações de variáveis são normalmente usadas para dicas de tipo: por exemplo, espera-se que esta variável
receba valores do tipo int:
count: int = 0
127
Python Tutorial, Release 3.9.1
Esses documentos são gerados a partir de reStructuredText pelo Sphinx, um processador de documentos especifica-
mente escrito para documentação do Python.
O desenvolvimento da documentação e de suas ferramentas é um esforço totalmente voluntário, como o Python em
si. Se você quer contribuir, por favor dê uma olhada na página reporting-bugs para informações sobre como fazer.
Novos voluntários são sempre bem-vindos!
Agradecimentos especiais para:
• Fred L. Drake, Jr., o criador do primeiro conjunto de ferramentas para documentar o Python e escritor de boa
parte do conteúdo;
• O projeto Docutils por criar reStructuredText e o pacote Docutils;
• Fredrik Lundh por seu projeto Referência Alternativa para Python do qual Sphinx teve muitas ideias boas.
Muitas pessoas tem contribuído para a linguagem Python, sua biblioteca padrão e sua documentação. Veja
Misc/ACKS na distribuição do código do Python para ver uma lista parcial de contribuidores.
Tudo isso só foi possível com o esforço e a contribuição da comunidade Python, por isso temos essa maravilhosa
documentação – Obrigado a todos!
129
Python Tutorial, Release 3.9.1
História e Licença
O Python foi criado no início dos anos 1990 por Guido van Rossum na Stichting Mathematisch Centrum (CWI,
veja https://www.cwi.nl/) na Holanda como um sucessor de uma linguagem chamada ABC. Guido continua a ser o
principal autor de Python, embora inclua muitas contribuições de outros.
Em 1995, Guido continuou seu trabalho em Python na Corporação para Iniciativas Nacionais de Pesquisa (CNRI,
veja https://www.cnri.reston.va.us/) em Reston, Virgínia, onde lançou várias versões do software.
Em maio de 2000, Guido e a equipe principal de desenvolvimento do Python mudaram-se para o BeOpen.com para
formar a equipe BeOpen PythonLabs. Em outubro do mesmo ano, a equipe da PythonLabs mudou para a Digital
Creations (agora Zope Corporation; veja https://www.zope.org/). Em 2001, formou-se a Python Software Foundation
(PSF, ver https://www.python.org/psf/), uma organização sem fins lucrativos criada especificamente para possuir
propriedade intelectual relacionada a Python. A Zope Corporation é um membro patrocinador do PSF.
Todas as versões do Python são de código aberto (consulte https://opensource.org/ para a definição de código aberto).
Historicamente, a maioria, mas não todas, versões do Python também são compatíveis com GPL; a tabela abaixo
resume os vários lançamentos.
Nota: Compatível com a GPL não significa que estamos distribuindo Python sob a GPL. Todas as licenças do
Python, ao contrário da GPL, permitem distribuir uma versão modificada sem fazer alterações em código aberto. As
131
Python Tutorial, Release 3.9.1
licenças compatíveis com a GPL possibilitam combinar o Python com outro software lançado sob a GPL; os outros
não.
Graças aos muitos voluntários externos que trabalharam sob a direção de Guido para tornar esses lançamentos pos-
síveis.
prepared by Licensee.
agrees to include in any such work a brief summary of the changes made␣
,→to Python
3.9.1.
USE OF PYTHON 3.9.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.9.1
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A␣
,→RESULT OF
Agreement does not grant permission to use PSF trademarks or trade name␣
,→in a
third party.
2. Subject to the terms and conditions of this BeOpen Python License Agreement,
BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license
to reproduce, analyze, test, perform and/or display publicly, prepare derivative
works, distribute, and otherwise use the Software alone or in any derivative
version, provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR
ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING,
MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF
ADVISED OF THE POSSIBILITY THEREOF.
2. Subject to the terms and conditions of this License Agreement, CNRI hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python 1.6.1 alone or in any derivative version,
provided, however, that CNRI's License Agreement and CNRI's notice of copyright,
i.e., "Copyright © 1995-2001 Corporation for National Research Initiatives; All
Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version
prepared by Licensee. Alternately, in lieu of CNRI's License Agreement,
Licensee may substitute the following text (omitting the quotes): "Python 1.6.1
is made available subject to the terms and conditions in CNRI's License
Agreement. This Agreement together with Python 1.6.1 may be located on the
Internet using the following unique, persistent identifier (known as a handle):
1895.22/1013. This Agreement may also be obtained from a proxy server on the
Internet using the following URL: http://hdl.handle.net/1895.22/1013."
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR
ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE
THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided that
the above copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation, and that
the name of Stichting Mathematisch Centrum or CWI not be used in advertising or
publicity pertaining to distribution of the software without specific, written
prior permission.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
Esta seção é uma lista incompleta, mas crescente, de licenças e confirmações para softwares de terceiros incorporados
na distribuição do Python.
C.3.2 Sockets
O módulo socket usa as funções getaddrinfo() e getnameinfo(), que são codificadas em arquivos de
origem separados do Projeto WIDE, http://www.wide.ad.jp/.
THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Permission to use, copy, modify, and distribute this Python software and
its associated documentation for any purpose without fee is hereby
granted, provided that the above copyright notice appears in all copies,
and that both that copyright notice and this permission notice appear in
supporting documentation, and that the name of neither Automatrix,
Bioreason or Mojam Media be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
C.3.8 test_epoll
Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes
All rights reserved.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
C.3.10 SipHash24
<MIT License>
Copyright (c) 2013 Marek Majkowski <[email protected]>
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
</MIT License>
Original location:
https://github.com/majek/csiphash/
O arquivo Python/dtoa.c, que fornece as funções C dtoa e strtod para conversão de duplas de C para e de strings,
é derivado do arquivo com o mesmo nome de David M. Gay, atualmente disponível em http://www.netlib.org/fp/. O
arquivo original, conforme recuperado em 16 de março de 2009, contém os seguintes avisos de direitos autorais e de
licenciamento:
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
C.3.12 OpenSSL
Os módulos hashlib, posix, ssl, crypt usam a biblioteca OpenSSL para desempenho adicional se forem
disponibilizados pelo sistema operacional. Além disso, os instaladores do Windows e do Mac OS X para Python
podem incluir uma cópia das bibliotecas do OpenSSL, portanto incluímos uma cópia da licença do OpenSSL aqui:
LICENSE ISSUES
==============
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
please contact [email protected].
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* [email protected].
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
(continua na próxima página)
C.3.13 expat
A extensão pyexpat é construída usando uma cópia incluída das fontes de expatriadas, a menos que a compilação
esteja configurada --with-system-expat:
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
and Clark Cooper
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
C.3.14 libffi
A extensão _ctypes é construída usando uma cópia incluída das fontes libffi, a menos que a compilação esteja
configurada --with-system-libffi:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
C.3.15 zlib
A extensão zlib é construída usando uma cópia incluída das fontes zlib se a versão do zlib encontrada no sistema
for muito antiga para ser usada na construção:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
C.3.16 cfuhash
C.3.17 libmpdec
O módulo _decimal é construído usando uma cópia incluída da biblioteca libmpdec, a menos que a compilação
esteja configurada --with-system-libmpdec:
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
O conjunto de testes C14N 2.0 no pacote test (Lib/test/xmltestdata/c14n-20/) foi recuperado do site
do W3C em https://www.w3.org/TR/xml-c14n2-testcases/ e é distribuído sob a licença BSD de 3 cláusulas:
Copyright (c) 2013 W3C(R) (MIT, ERCIM, Keio, Beihang), All Rights Reserved.
A redistribuição e uso nas formas de fonte e binárias, com ou sem modificação, são permitidas desde
que as seguintes condições sejam atendidas:
• As redistribuições de obras devem manter o aviso de direitos autorais original, esta lista de condi-
ções e o aviso de isenção de responsabilidade a seguir.
• As redistribuições em formato binário devem reproduzir o aviso de direitos autorais original, esta
lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e/ou outros
materiais fornecidos com a distribuição.
• Nem o nome do W3C nem os nomes de seus colaboradores podem ser usados para endossar ou
promover produtos derivados deste trabalho sem permissão prévia por escrito específica.
ESTE SOFTWARE É FORNECIDO PELOS DETENTORES DE DIREITOS AUTORAIS E CON-
TRIBUIDORES “COMO ESTÁ” E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, IN-
CLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZA-
ÇÃO E ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO. EM NENHUM CASO O DETENTOR
DE DIREITOS AUTORAIS OU OS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUAL-
QUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQUEN-
CIAL (INCLUINDO, MAS NÃO SE LIMITANDO A, PROCURAÇÃO DE BENS OU SERVIÇOS
SUBSTITUTOS; PERDA DE USO, DADOS, LUCROS DE USO; OU INTERRUPÇÃO DE NEGÓ-
CIOS), CAUSADO E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATADA, RES-
PONSABILIDADE RÍGIDA OU ATRIBUIÇÃO (INCLUINDO NEGLIGÊNCIA OU DE OUTRA
FORMA), SURGINDO DE ALGUMA FORMA FORA DO USO DESTE SOFTWARE, MESMO
QUE SEJA ACONSELHÁVEL A POSSIBILIDADE DE TAL CONTEÚDO.
Direitos autorais
149
Python Tutorial, Release 3.9.1
151
Python Tutorial, Release 3.9.1
J P
json pacote, 123
módulo, 61 pacote de espaço de nomes, 123
pacote provisório, 125
L pacote regular, 126
lambda, 122 parâmetro, 124
LBYL, 122 PATH, 47, 113
lista, 122 path
localizador, 119 module search, 47
localizador baseado no caminho, 124 PEP, 124
localizador de entrada de caminho, 124 porção, 125
152 Índice
Python Tutorial, Release 3.9.1
R
RFC
RFC 2822, 90
S
search
path, module, 47
sequência, 126
special
method, 126
strings, documentation, 23, 31
style
coding, 32
sys
módulo, 48
T
tipagem pato, 118
tipo, 126
tipo alias, 127
tipo genérico, 120
tupla nomeada, 123
V
váriavel de ambiente
PATH, 47, 113
PYTHONPATH, 47, 49
PYTHONSTARTUP, 114
variável de classe, 117
Índice 153