Vous êtes sur la page 1sur 50

Introdução à Programação de

Computadores com Python∗


1.a edição

Prof.o Sidney Roberto de Sousa

Conteúdo
1 Criando e executando um programa em Python . . . . . . . . . . 1
2 Imprimindo texto na tela . . . . . . . . . . . . . . . . . . . . . . 3
3 Criando comentários . . . . . . . . . . . . . . . . . . . . . . . . 4
4 Lendo valores do usuário . . . . . . . . . . . . . . . . . . . . . . 5
5 Trabalhando com strings . . . . . . . . . . . . . . . . . . . . . . 6
6 Trabalhando com números inteiros . . . . . . . . . . . . . . . . 11
7 Trabalhando com números reais . . . . . . . . . . . . . . . . . . 12
8 Operações matemáticas . . . . . . . . . . . . . . . . . . . . . . 13
9 Trabalhando com booleanos e operações lógicas . . . . . . . . . 16
10 Controlando o fluxo do programa . . . . . . . . . . . . . . . . . 18
11 Utilizando laços de repetição . . . . . . . . . . . . . . . . . . . 24
12 Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
13 Dicionários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
14 Manipulação de arquivos . . . . . . . . . . . . . . . . . . . . . . 40
15 Lidando com erros . . . . . . . . . . . . . . . . . . . . . . . . . 47

1 Criando e executando um programa em Python


Um programa Python básico é escrito dentro de um script Python. Um script
Python é simplesmente um arquivo textual contendo linhas de código escritas
utilizando a linguagem de programação Python. Estas linhas, em conjunto,
contém instruções para fazer o computador realizar alguma tarefa.
Para criar um script Python, primeiramente você deve escolher um editor de
texto adequado. Um editor de texto é um programa pelo qual é possı́vel criar,
editar e salvar arquivos que contém basicamente texto simples – como os scripts

Este material está baseado no Python 3≥3.4.

1
1 Criando e executando um programa em Python 2

Python, por exemplo. Existem diversos editores de texto disponı́veis na internet.


Em nossas aulas, utilizaremos o editor Notepad++1 . Este editor de texto possui
a capacidade de destacar as palavras reservadas da linguagem Python, o que
auxiliará bastante na criação de nossos scripts.
Para criar um novo script Python, você deve abrir o Notepad++, clicar no
menu Arquivo e então na opção Novo. Após, clique no menu Arquivo nova-
mente e então clique na opção Salvar como. Ao abrir a janela Salvar como,
escolha uma pasta para o seu arquivo e dê um nome ao seu script, preferenci-
almente, utilizando letras minúsculas, sem espaços em branco, acentuações ou
caracteres especiais. Ainda na nomenclatura do seu arquivo, utilize a extensão
.py. Esta extensão é utilizada para se identificar scripts Python no sistema ope-
racional.
Uma vez que o script Python foi criado, é possı́vel executar o programa
escrito nele utilizando o interpretador do Python. Para tanto, basta executar o
comando python no Prompt de Comando do Windows. Por exemplo, digamos
que o script exemplo.py tenha sido salvo na pasta
C:\Users\sidney.sousa\CursoPython. No Prompt de Comando, é preciso
entrar nesta pasta utilizando o comando cd. Após, utilizamos o comando python
para executar o script. A figura 1 exibe este processo.

Fig. 1: Abrindo a pasta onde o script está contido e, por fim, executando o script.

Como nosso script ainda não possui nenhuma linha de código, nada é impresso
na tela após executarmos o comando python. Na próxima seção, começaremos
a programar o nosso script!
1
Disponı́vel em https://notepad-plus-plus.org/. Acessado em 4 de abril de 2016.
2 Imprimindo texto na tela 3

2 Imprimindo texto na tela


Ainda no script exemplo.py da seção anterior, iremos criar um programa para
imprimir na tela uma mensagem para o usuário. Para tanto, utilizaremos a função
print, a qual recebe como parâmetro uma mensagem de texto. Esta mensagem
deve estar dentro de aspas simples, aspas duplas ou aspas triplas. Nesta apostila,
por padrão, utilizaremos aspas simples na impressão de mensagens nos exemplos.
A seguir, o script exemplo.py utiliza a função print para imprimir três mensagens
na tela, cada qual utilizando um padrão de aspas:
1 print ( ’Olá , mundo ! ’)
2 print ( " Eu também sou uma mensagem ! " )
3 print ( ’’’ ... e eu também sou uma mensagem ! ’’’)
Após executarmos este script, a saı́da será a seguinte:
1 Olá , mundo !
2 Eu também sou uma mensagem !
3 ... e eu também sou uma mensagem !
Como você pode ver, cada mensagem apareceu em uma linha diferente. Isto
ocorreu porquê cada mensagem foi impressa utilizando uma chamada diferente
à função print. Porém, é possı́vel imprimir mais de uma mensagem utilizando
uma única chamada à função print. Para tanto, é preciso utilizar o caractere
não imprimı́vel \n. Observe o exemplo a seguir:
1 print ( ’ Primeira linha .\ nSegunda linha .\ nTerceira linha . ’)

A saı́da da execução deste exemplo será:


1 Primeira linha .
2 Segunda linha .
3 Terceira linha .
No exemplo acima, o caractere \n forçou a quebra de linha no ponto em que
ele foi inserido. O resultado disso é que a mensagem original foi dividida em três
linhas.
Outro efeito possı́vel na impressão de texto na tela é a tabulação, utilizando
o caractere não imprimı́vel \t. Como exemplo, considere o script abaixo:
1 print ( ’ Esta frase n~
a o possui tabulaç~a o . ’)
2 print ( ’\ tEsta frase possui tabulaç~
a o . ’)
Saı́da:
1 Esta frase n~
a o possui tabulaç~
ao .
2 Esta frase possui tabulaç~
ao .
3 Criando comentários 4

No exemplo acima, o caractere \t forçou uma tabulação no inı́cio da segunda


frase. Cada ocorrência do caractere \t força uma tabulação, conforme exibe o
exemplo abaixo:
1 print ( ’ Esta frase n~ a o possui tabulaç~
a o . ’)
2 print ( ’\ t \ t \ tEsta frase possui 3 tabulaç~ o es . ’)
Saı́da:
1 Esta frase n~
a o possui tabulaç~
ao .
2 Esta frase possui 3 tabulaç~
o es .

Exercı́cios:
(a) Escreva um script que imprima na tela o poema a seguir utilizando uma
ou mais chamadas à função print, sabendo que cada frase possui uma
tabulação em seu inı́cio.
1 BILHETE
2
3 Se tu me amas , ama - me baixinho
4 N~
a o o grites de cima dos telhados
5 Deixa em paz os passarinhos
6 Deixa em paz a mim !
7 Se me queres ,
8 enfim ,
9 tem de ser bem devagarinho , Amada ,
10 que a vida é breve , e o amor mais breve ainda
11

12 Mario Quintana

(b) Escreva um script que imprima na tela o mesmo poema acima, porém
utilizando somente uma chamada à função print.

3 Criando comentários
Um comentário consiste em uma anotação ou lembrete que você deseja colocar
no código do seu script. Comentários não são código Python e não afetam em
nada a execução do seu script. Observe o exemplo abaixo:
1 # A linha abaixo exibe uma mensagem pro usuário
2 print ( ’Olá , seja bem vindo ! ’)
O script acima contém duas linhas. A primeira linha contém um comentário
explicando ao leitor do código do script o que a linha de código abaixo faz. Para
criar um comentário de uma única linha, assim como o do exemplo acima, basta
4 Lendo valores do usuário 5

colocar no inı́cio da linha o caractere #. Caso este caractere seja colocado no


inı́cio de uma linha de código válida, este código é desabilitado e, consequente-
mente, não executado. No exemplo abaixo, desabilitamos a linha do script do
exemplo anterior que imprime a mensagem na tela:
1 # A linha abaixo exibe uma mensagem pro usuário
2 # print ( ’ Olá , seja bem vindo ! ’)
É possı́vel criar comentários com duas ou mais linhas. Porém, para isto é
necessário inserir três aspas simples antes e depois do texto de comentário. O
exemplo abaixo exibe o uso de comentários de várias linhas:
1 ’’’
2 É possı́vel criar comentários de várias linhas ,
3 utilizando aspas triplas no inı́cio e no final do
4 comentário .
5 ’’’
6 print ( ’ Lembre - se : comentários n~
a o s~
a o trechos de código válidos ! ’)

Utilize comentários sempre que desejar deixar algum lembrete a si mesmo ou


a outra pessoa sobre o seu código. Nesta apostila, comentários serão utiliza-
dos esporadicamente nos scripts de exemplo para deixar alguma observação ou
lembrete.

4 Lendo valores do usuário


Todos os programas dos scripts vistos até então nesta apostila não são interativos.
Ou seja, eles não promovem a interação direta entre o usuário e computador.
A partir de agora, vamos aprender a ler dados do usuário a fim de alimentar os
nossos programas.
Primeiramente, iremos aprender a realizar a leitura de uma mensagem de
texto do usuário. O script abaixo pergunta ao usuário o seu nome e então exibe
na tela uma mensagem cordial:
1 nome = input ( ’ Informe o seu nome : ’)
2 print ( ’Olá , % s ! ’% nome )
A primeira linha do script acima realiza as seguintes tarefas. Primeiramente,
a função input exibe na tela uma mensagem solicitando o nome do usuário. Em
seguida, o cursor do Prompt do Windows irá esperar que o usuário digite o dado
solicitado. Após digitar o seu nome, o usuário deve digitar a tecla ENTER para
confirmar a leitura.
Por fim, a função input retorna o nome digitado pelo usuário, o qual é arma-
zenado na variável nome. Isto é feito por meio de uma operação de atribuição.
Uma operação de atribuição possui a seguinte estrutura:

variável = código que resulta em algum valor


5 Trabalhando com strings 6

Operações de atribuição são divididas em duas partes, separadas pelo opera-


dor de atribuição =. Elas devem ser analisadas da direita para a esquerda. O
lado direito de uma operação de atribuição sempre contém algum código que
irá resultar em algum valor — por exemplo, uma equação matemática, uma
função que retorna algum valor, entre outros. Por sua vez, o lado esquerdo de
uma operação de atribuição, na maioria das vezes, contém uma variável que irá
armazenar o valor gerado no lado direito da operação.
Neste ponto, você deve estar se perguntando: o que é uma variável?
Uma variável representa um espaço de memória onde um determinado valor
é armazenado. No exemplo anterior, a variável nome representa o espaço de
memória onde o nome do usuário é salvo para ser utilizado durante o programa
escrito no script. Quando a execução do script termina, a variável é destruı́da e,
assim, seu valor é perdido.
Voltando ao último exemplo, na segunda linha do script é impressa uma
mensagem cordial ao usuário, utilizando a função print. Para que o valor da
variável nome possa ser impresso, é utilizado o caractere %s na mensagem
dentro da função print. Ele funciona como um “coringa”, sendo substituı́do
em tempo de execução pelo valor da variável nome, a qual é passada na função
print utilizando como prefixo o caractere %. Este prefixo informa à função print
que o valor a ser colocado no lugar do caractere %s está na variável nome. A
seguir, um exemplo de execução do script do exemplo anterior:
1 Informe o seu nome : Sidney
2 Olá , Sidney !

5 Trabalhando com strings


Uma string é basicamente um conjunto de caracteres. Uma palavra, uma frase
ou um texto composto por várias frases são exemplos de strings. Na seção
anterior, vimos um exemplo de script que lia o nome do usuário e o armazenava
na variável nome. Podemos dizer que, neste exemplo, a variável nome contém
uma string.
As strings são muito importantes na programação de computadores. Muitos
dos dados que são processados e armazenados em sistemas de informação são
strings. Por exemplo, em um sistema de gestão escolar, temos vários dados
que são strings, como por exemplo o nome do estudante, seu endereço e o
nome de seu responsável. Temos ainda os nomes dos cursos, disciplinas, turmas,
professores e outros dados que também são strings.
Em um sistema de e-commerce, várias strings são processadas e armazenadas,
como os nomes dos produtos, suas descrições, opiniões de clientes, etc. De fato,
em muitos sistemas comerciais, boa parte dos dados consiste basicamente em
5 Trabalhando com strings 7

strings. Além disso, o uso de strings não se atém a sistemas comerciais, mas
também é visto em softwares cientı́ficos, sistemas operacionais e muitos outros
tipos de sistemas.
Desta forma, saber escrever programas que processam strings é algo crucial
para um bom programador de computadores. A boa notı́cia é que a linguagem
de programação Python possui um suporte bem completo para o processamento
de strings.
Mas afinal, o que é processar uma string? O que isto significa?
Processar uma string consiste em realizar nela alguma dentre as seguintes
operações:

• Transformá-la em outra string;


• Selecionar de forma estratégica parte dela;
• Particioná-la de forma estratégica.

Antes de aprender como realizar todas estas operações, você precisa entender
a definição sobre strings da primeira frase desta seção: uma string é basicamente
um conjunto de caracteres. Na teoria dos conjuntos, um conjunto pode ser
composto por nenhum elemento, um único elemento ou vários elementos. No
caso das strings, podemos dizer que uma string pode ser composta por nenhum
caractere (o que chamamos de string vazia), um único caractere ou vários
caracteres, conforme o exemplo abaixo:
1 string1 = ’ ’
2 string2 = ’a ’
3 string3 = ’ Eu possuo vários caracteres ’
No exemplo acima, cada string sendo atribuı́da a uma variável é cercada por
aspas simples. Toda string deve ser cercada por aspas, aspas simples ou aspas
triplas, conforme o exemplo abaixo:
1 string1 = ’Olá , mundo ! ’
2 string2 = " Eu também sou uma string ! "
3 string3 = ’’’ ... e eu também sou uma string ! ’’’
Você pode escolher que forma de cercamento você irá utilizar. Porém, caso
você cerque o inı́cio de uma string com um tipo de aspas, o cercamento do final
da string deve utilizar o mesmo tipo de aspas. Caso contrário, você terá um erro
de sintaxe no seu código e então seu script não será executado.
Cada caractere dentro de uma string possui um ı́ndice, que funciona como
um endereço do caractere dentro da string. O Python trabalha com dois tipos
de indexação de caracteres: a indexação padrão e a indexação negativa. A
tabela 1 exemplifica a indexação de caracteres de uma string em Python:
5 Trabalhando com strings 8

O l á , m u n d o !
0 1 2 3 4 5 6 7 8 9 10
-11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

Tab. 1: Indexação de strings em Python

Desta forma, podemos dizer que, na indexação padrão, o caractere ‘!’ está
localizado na posição de ı́ndice 10, enquanto que o caractere ‘,’ está localizado
na posição de ı́ndice 3. Se utilizarmos a indexação negativa, podemos dizer que
o caractere ‘!’ está localizado na posição de ı́ndice -1, enquanto que o caractere
‘,’ está localizado na posição de ı́ndice -8.
É possı́vel pegar caracteres de uma string, utilizando o ı́ndice no qual o
caractere está localizado, conforme exibido no script a seguir:
1 frase = ’ Ontem eu vi um animal . ’
2 print ( frase [0]) # ’O ’
3 print ( frase [6]) # ’e ’
4 print ( frase [ -3]) # ’a ’
5 print ( frase [ -10]) # ’u ’
O uso de ı́ndices também permite a extração de parte de uma string, ou seja,
uma substring. Para tanto, é preciso saber qual o ı́ndice do primeiro e últimos
caracteres da substring a ser extraı́da.
Como exemplo, considere a string “Três tigres tristes”. Agora, imagine que
devemos extrair a substring “Três” desta string. Para tanto, devemos encontrar
os ı́ndices dos caracteres ‘T’ e ‘s’, respectivamente os caracteres inicial e final
desta substring:

T r ê s
0 1 2 3

Tab. 2: Indexação da string “Três”.

Assim, os caracteres encontram-se nos ı́ndices 0 e 3 da substring. O script


abaixo realiza a extração da substring “Três” da string “Três tigres tristes”:
1 string = ’ Tr^e s tigres tristes ’
2 substring = string [0:4] # extrai a substring ’ Tr^
es ’
3 print ( substring )
A extração ocorre na segunda linha do script, com a diretiva string[0:4].
Dentro dos colchetes da string, foram passados os ı́ndices 0 e 4, definindo os
ı́ndices de inı́cio e final do corte.
Neste momento você pode estar se perguntando: “Mas o ı́ndice final da
substring ‘Três’ não era 3?”. De fato, 3 é o ı́ndice final da substring. Porém, nas
5 Trabalhando com strings 9

diretivas de extração de substrings, o ı́ndice de inı́cio do corte é inclusivo e o de


fim é exclusivo. Ou seja, a substring resultante conterá todos os caracteres (em
ordem) contidos a partir do ı́ndice de inı́cio até o caractere contido no último
ı́ndice anterior ao ı́ndice de fim de corte.
Para entender este mecanismo, execute e observe o script abaixo:
1 string = ’ Tr^e s tigres tristes ’
2 substring = string [0:4] # extrai a substring ’ Tr^
es ’
3 print ( substring )
4 substring = string [5:11] # extrai a substring ’ tigres ’
5 print ( substring )
6 substring = string [12:19] # extrai a substring ’ tristes ’
7 print ( substring )
Agora, imagine que devemos escrever um programa que leia do usuário uma
frase e então deva extrair desta frase o primeiro e último caracteres. Bem, extrair
o primeiro caractere de uma frase é simples, haja visto que ele sempre estará no
primeiro ı́ndice, ou seja, o ı́ndice 0:
1 frase = input ( ’ Digite uma frase ’)
2 primeiro = frase [0]
3 print ( primeiro )
Porém, como faremos para extrair o último caractere da frase, considerando
que não sabemos de antemão qual frase o usuário digitará?
Bem, neste caso existem duas estratégias possı́veis: a primeira consiste em
descobrir qual o tamanho da frase; em seguida, com base neste dado, calculare-
mos qual é o ı́ndice do último caractere da frase. Considere a frase a seguir:

L u a c h e i a !
0 1 2 3 4 5 6 7 8 9

Tab. 3: Frase de exemplo.

A frase acima possui exatamente 10 caracteres2 . Assim, dizemos que ela pos-
sui tamanho 10. Em Python, o tamanho de uma string é dado pela quantidade
de caracteres que ela possui.
Desta forma, na string acima, os ı́ndices de seus caracteres variam de 0 a
9. Ou seja, o último caractere está no ı́ndice 9. Assim, se uma string possui
tamanho n, o último caractere estará sempre no ı́ndice n – 1.
Voltando ao nosso problema, para encontrar o último caractere da frase infor-
mada pelo usuário, devemos encontrar primeiramente o tamanho da string. Para
2
Vale salientar que o espaço em branco, na quarta posição (ı́ndice 3) também é um caractere
válido.
5 Trabalhando com strings 10

tanto, utilizaremos a função len (de length, ou comprimento, em português) do


Python:
1 frase = input ( ’ Digite uma frase : ’)
2 primeiro = frase [0]
3 tamanho = len ( frase )
4 ultimo = frase [ tamanho - 1]
5 print ( ’ Primeiro : % s \ t Último : % s ’ %( primeiro , ultimo ) )
A segunda estratégia é bem mais simples. Ela consiste simplesmente em
utilizar o sistema de indexação negativa do Python, conforme exibido na tabela
1. Nela, o último caractere de uma string sempre está no ı́ndice -1. O script a
seguir utiliza esta estratégia mais simples:
1 frase = input ( ’ Digite uma frase : ’)
2 primeiro = frase [0]
3 ultimo = frase [ -1]
4 print ( ’ Primeiro : % s \ t Último : % s ’ %( primeiro , ultimo ) )
Ora ou outra, existe a necessidade de concatenar duas ou mais strings, de
tal maneira a formar uma única string resultante. Para tanto, é possı́vel utilizar
o operador +, conforme exibido no script a seguir:
1 frase1 = ’ Estamos ’
2 frase2 = ’ ’
3 frase3 = ’ juntas ! ’
4 frase_completa = frase1 + frase2 + frase3
5 print ( frase_completa ) # Estamos juntas !
Também é possı́vel converter strings para maiúsculo ou minúsculo, utilizando
as funções embutidas upper e lower. No script abaixo, a primeira string é
convertida para maiúsculo, enquanto que a segunda string tem sua primeira
metade convertida para maiúsculo e sua segunda metade para minúsculo:
1 frase1 = ’ Eu e minha ^ a nsia por crescer ! ’
2 print ( frase1 . upper () )
3 frase2 = ’ N~ a o sei se quero crescer ou ficar na inf^
a ncia . ’
4 ’’’
5 Nas duas linhas abaixo , para calcular o valor
6 da metade do tamanho da frase , é utilizado a
7 funç~
a o len () para calcular o tamanho da frase
8 e ent~ a o utilizado o operador / para dividir o
9 tamanho por 2 , a funç~ a o int () para converter
10 o resultado para um valor inteiro e ent~ ao o
11 operador + para somar uma unidade ao resultado .
12 Fique tranquilo caso n~ a o tenha entendido
13 completamente o script abaixo ! Veremos mais
14 sobre operaç~ o es matemáticas em breve .
6 Trabalhando com números inteiros 11

15 ’’’
16 tamanho = len ( frase2 )
17 metade = int ( tamanho / 2) + 1
18 primeira = frase2 [0: metade ]. upper ()
19 segunda = frase2 [ metade : tamanho ]. lower ()
20 frase2 = primeira + segunda
21 print ( frase2 )
Outra operação muito comum quando lidamos com string é ter que substituir
uma determinada substring de uma determinada string por outra substring. Para
tanto, é possı́vel utilizar a função embutida replace, conforme o script abaixo:
1 frase = ’A Ana comeu banana ... mas que sacana ! ’
2 # A Ana comeu banana ... mas que espertinha !
3 print ( frase . replace ( ’ sacana ’ , ’ espertinha ’) )
4 # A Ana comeu bANAna ... mas que sacANA !
5 print ( frase . replace ( ’ ana ’ , ’ ANA ’) )
Por fim, uma operação comum a se realizar em strings é remover espaços
em branco no inı́cio e no final. Muitas vezes, usuários ao preencher formulários
acabam deixando espaços em branco indesejados nestas posições. Para resolver
este problema, podemos utilizar a função embutida strip, conforme o exemplo a
seguir:
1 frase = ’ por favor , remova estes espaços em branco ’
2 print ( frase . strip () )

Exercı́cios
(a) Escreva um script que leia do usuário uma frase e então divida esta frase
em três partes, exibindo todas as três partes na tela ao final.
(b) Escreva um script que leia do usuário uma frase e então insira o caractere
‘[’ no inı́cio da frase e o caractere ‘]’ no final desta.
(c) Escreva um script que armazene cada palavra da string “Um dia eu fui
uma string completa...” em uma variável distinta, realizando os cortes
necessários na string.

6 Trabalhando com números inteiros


Muitos dos problemas do mundo real que necessitam de um programa de com-
putador para serem resolvidos envolvem números.
Considere o seguinte problema: uma pessoa possui 53 pacotes de biscoito
salgado e 87 pacotes de biscoito doce em seu estoque e ela precisa saber quantos
7 Trabalhando com números reais 12

pacotes de biscoito ela possui no total. Note que este problema envolve apenas
números inteiros, ou seja, números que não precisam de casas decimais para
representá-los. Vamos escrever um script para resolver este problema:
1 n r o _ p a c o t e s _ b i s c o i t o _ s a l g a d o = 53
2 n r o _ p a c o t e s _ b i s c o i t o _ d o c e = 87
3 total_pacotes = n r o _ p a c o t e s _ b i s c o i t o _ s a l g a d o + n r o _ p a c o t e s _ b i s c o i t o _ d o c e
4 print ( ’ Voc^ e possui % d pacotes de biscoito . ’% total_pacotes )

Para resolver este problema, precisamos utilizar três variáveis. Como dito na
seção 4, uma variável é um local de armazenamento de dados. Você pode pen-
sar em uma variável como uma gaveta capaz de armazenar itens. Toda variável
possui um nome, o qual deve começar com uma letra e não pode conter carac-
teres especiais, como espaços em branco, sı́mbolos e sinais diversos. A PEP 83
recomenda que variáveis sejam nomeadas utilizando somente letras minúsculas,
com as palavras separadas por um “underline” ( ).
A primeira variável utilizada no programa acima chama-se
nro pacotes biscoito salgado. Ela guarda o número de pacotes de biscoito
salgado contidos no estoque da pessoa do nosso problema. A segunda variável
do nosso programa chama-se nro pacotes biscoito doce. Por sua vez, ela
guarda o número de pacotes de biscoito doce existentes no estoque.
O número total de pacotes é exibido na última linha do programa. A fim de
facilitar o entendimento do usuário a respeito do que foi realizado no programa,
exibimos a ele uma frase explicativa contendo o número total de pacotes calcu-
lado. Note que utilizamos o caractere %d como coringa para substituir o valor
da variável total pacotes na frase do usuário. Tivemos que utilizar %d ao invés
de %s, uma vez que o valor sendo inserido não é uma string, mas um número
inteiro (‘d’ vem de decimal). O programa exibe a seguinte saı́da na tela:
1 Voc^
e possui 140 pacotes de biscoito .

7 Trabalhando com números reais


Agora, imagine que a pessoa do exemplo anterior deseje saber qual o peso total
dos biscoitos que ela possui em estoque. Ela sabe que cada pacote de biscoito
salgado pesa 0,350 kg e cada pacote de biscoito doce pesa 0,414 kg. Note que
agora alguns números do nosso problema não são inteiros — no caso, os pesos
dos pacotes. Assim, não podemos trabalhar com os valores como se fossem
números inteiros. A seguir, a solução para este problema:
3
Python Enhancement Proposal (em português, Proposta de Melhoria Python). A PEP
8 está disponı́vel em https://www.python.org/dev/peps/pep-0008/. Acessado em 6 de
maio de 2016.
8 Operações matemáticas 13

1 n r o _ p a c o t e s _ b i s c o i t o _ s a l g a d o = 53
2 n r o _ p a c o t e s _ b i s c o i t o _ d o c e = 87
3 p e s o _ b i s c o i t o s _ s a l g a d o s = n r o _ p a c o t e s _ b i s c o i t o _ s a l g a d o * 0.350
4 p e s o _ b i s c o i t o s _ d o c e s = n r o _ p a c o t e s _ b i s c o i t o _ d o c e * 0.414
5 peso_total_pacotes = peso_biscoitos_salgados + peso_biscoitos_doces
6 print ( ’O seu estoque de biscoitos pesa % f kg . ’% p e s o _ t o t a l _ p a c o t e s )

Além das duas variáveis para armazenar o número total de pacotes de cada
tipo de biscoito, o nosso programa possui mais três variáveis para armazenar o
peso total de biscoitos salgados, o peso total de biscoitos doces e o peso total
de biscoitos em estoque. Diferentemente das duas variáveis anteriores, estas
variáveis armazenam números reais, ou seja, números com casas decimais.
Note que na mensagem de resposta na função print utilizamos o caractere %f
como coringa para injetar o valor da variável peso total pacotes. Neste caso,
utilizamos o caractere %f pois o valor a ser injetado era um valor real (‘f’ vem de
floating point, ou ponto flutuante, em português). O script anterior imprime
a mensagem na tela:
1 O seu estoque de biscoitos pesa 54.568000 kg .
Note que o número do resultado possui três zeros nas últimas casas deci-
mais. É possı́vel arredondar este número na impressão dentro da função print,
adaptando o caractere %f:
1 print ( ’O seu estoque de biscoitos pesa %.2 f kg . ’% p e s o _ t o t a l _ p a c o t e s )

Na linha acima, modificamos o caractere %f para %.2f, o que faz com que o
número seja arredondado utilizando-se apenas duas casas decimais após o ponto.
Como resultado, a mensagem abaixo será exibida:
1 O seu estoque de biscoitos pesa 54.57 kg .

8 Operações matemáticas
Uma operação binária é uma operação matemática que envolve dois valores
distintos. Tais valores podem ser constantes ou oriundos de variáveis. Como
exemplo, vamos escrever um script para realizar a soma de dois números infor-
mados pelo usuário:
1 resposta = input ( ’ Digite o primeiro número : ’)
2 numero1 = int ( resposta )
3 resposta = input ( ’ Digite o segundo número : ’)
4 numero2 = int ( resposta )
5 resultado = numero1 + numero2
6 print ( ’% d + % d = % d ’ %( numero1 , numero2 , resultado ) )
No exemplo acima, precisamos realizar a leitura dos dois números a serem
somados, os quais são informados pelo usuário. Porém, a função input sempre
8 Operações matemáticas 14

retorna a resposta do usuário como string, o que impossibilitaria a realização


da soma dos valores informados. Desta forma, precisamos converter a resposta
do usuário que está em formato de string para um número inteiro, utilizando a
função int.
Aplicamos a função int para obter os valores que são armazenados nas
variáveis numero1 e numero2. Após realizar a soma dos valores e armaze-
nar o resultado na variável resultado, exibimos a mensagem de forma objetiva
ao usuário. Por exemplo, se o usuário informar os valores 67 e 88, a mensagem
abaixo será exibida na tela:
1 67 + 88 = 155
A tabela 4 mostra as operações matemáticas binárias possı́veis em Python.

Operação Operador Expressão


Adição + a=b+c
Subtração - a=b-c
Multiplicação * a=b*c
Divisão / a=b/c
Exponenciação ** a = b ** c
Módulo (resto) % a=b%c

Tab. 4: Operações matemáticas binárias da linguagem Python.

Operações matemáticas do tipo a = a OPERADOR b podem ser abrevia-


das. A tabela 5 mostra as abreviações possı́veis.

Expressão Expressão abreviada


a=a+c a += c
a=a-c a -= c
a=a*c a *= c
a=a/c a /= c
a = a ** c a **= c
a=a%c a %= c

Tab. 5: Abreviações possı́veis em operações matemáticas.

Podemos compor operações matemáticas mais complexas, como fórmulas


matemáticas que envolvem números reais. O script a seguir auxilia o usuário a
calcular a fórmula de Bhaskara:
1 resposta = input ( ’ Digite o valor de a : ’)
2 a = float ( resposta )
3 resposta = input ( ’ Digite o valor de b : ’)
8 Operações matemáticas 15

4 b = float ( resposta )
5 resposta = input ( ’ Digite o valor de c : ’)
6 c = float ( resposta )
7 delta = b ** 2 - 4 * a * c
8 print ( ’ delta = % f ’% delta )
No exemplo acima, os valores de a, b e c são reais. Para converter o valor
lido do usuário para real, utilizamos a função float. Na penúltima linha do script,
realizamos o cálculo do valor delta. Este cálculo envolve operações de exponen-
ciação, subtração e multiplicação. Em Python, algumas operações matemáticas
tem maior precedência sobre outras, ou seja, são calculadas antes que outras. A
tabela 8 mostra a ordem de precedência entre as operações matemáticas:

Ordem de precedência Operação


1o exponenciação e módulo
2o multiplicação e divisão
3o adição e subtração

Tab. 6: Ordem de precedência dos operadores matemáticos binários.

Desta forma, no cálculo do valor delta, a operação de exponenciação b ∗ ∗2 é


a primeira a ser calculada. Após, a cadeia de multiplicações 4 ∗ a ∗ c é calculada.
Por fim, a subtração entre os dois valores resultantes é calculada.
Caso a fórmula precise ser calculada utilizando uma ordem de precedência
diferente à ordem normal, é preciso utilizar parênteses para se definir os trechos
de precedência. Considere o exemplo a seguir:
1 resposta = input ( ’ Digite o primeiro número : ’)
2 numero1 = float ( resposta )
3 resposta = input ( ’ Digite o segundo número : ’)
4 numero2 = float ( resposta )
5 resultado = numero1 * (98 - numero2 ) * 4
6 print ( ’ Resultado : % f ’% resultado )
Note que na fórmula da penúltima linha a subtração 98 – numero2 seria
realizada por último, normalmente. Porém, como ela foi envolvida por parênteses,
ela será calculada primeiramente que as outras operações.

Exercı́cios
(a) Escreva um script que leia do usuário dois números inteiros a e b e então
calcule o valor de ab .
9 Trabalhando com booleanos e operações lógicas 16

(b) Escreva um script que leia do usuário o valor do raio de um cı́rculo e então
calcule o valor de sua área. A fórmula da área do cı́rculo é dada por:

area = Π ∗ raio2

onde Π = 3.14159265

(c) Escreva um script que leia do usuário o valor do montante a ser empres-
tado e a taxa de juros e então calcule o valor da parcela a ser paga pelo
empréstimo, considerando que as parcelas terão valor fixo. As fórmulas
para calcular o valor das parcelas a serem pagas pelo empréstimo são da-
das abaixo:

montante = valor ∗ (1 + ( taxa


100
∗ parcelas))
montante
prestacao = parcelas

onde montante é o valor final do empréstimo com a taxa de juros mensal


aplicada, valor é o valor a ser emprestado, taxa é taxa de juros mensal,
parcelas é a quantidade de parcelas e prestacao é o valor a ser pago em
cada parcela.

9 Trabalhando com booleanos e operações lógicas


Na linguagem Python, um valor booleano é um valor que só pode ter um dentre
dois valores: True ou False, respectivamente verdadeiro ou falso. Saber tra-
balhar com valores booleanos é essencial para a criação de programas complexos
em Python, conforme veremos a partir desta seção.
Em Python, um valor booleano pode ser armazenado em uma variável. Uma
operação realizada entre dois valores booleanos é chamada de operação lógica
(ou booleana) binária. O resultado de uma operação lógica só pode resultar em
um valor booleano, ou seja, True ou False.
Existem basicamente duas operações lógicas binárias: as operações and e
or. Uma operação and só resulta no valor True se e somente se os dois valores
da operação forem iguais a True; caso contrário, o resultado da operação será
False. A tabela 7 exibe os resultados para cada operação and possı́vel entre
dois valores booleanos:
Por sua vez, uma operação or só resulta no valor False se e somente se os
dois valores da operação forem iguais a False. A tabela 8 exibe os resultados
para cada operação or possı́vel entre dois valores booleanos:
Existe também em Python uma operação lógica unária, isto é, uma operação
que envolve apenas um valor: a operação de negação. Em Python, esta
9 Trabalhando com booleanos e operações lógicas 17

a b a and b
True True True
True False False
False True False
False False False

Tab. 7: Resultados possı́veis para a operação and.

a b a or b
True True True
True False True
False True True
False False False

Tab. 8: Resultados possı́veis para a operação or.

operação pode ser realizada por meio do operador not. A tabela 9 exibe os
valores possı́veis para cada operação de negação:

a not a
True False
False True

Tab. 9: Resultados possı́veis para a operação not.

O script abaixo mostra alguns exemplos de operações lógicas binárias e


unárias:
1 a = True
2 b = False
3 resultado = a and b
4 print ( resultado ) # False
5 resultado = a or b
6 print ( resultado ) # True
7 resultado = not a
8 print ( resultado ) # False
9 resultado = not b
10 print ( resultado ) # True
11 resultado = False and True or False or True
12 print ( resultado ) # True

É possı́vel criar operações lógicas envolvendo números inteiros ou reais. Exis-


tem muitas situações em que precisamos comparar dois ou mais números. As
10 Controlando o fluxo do programa 18

operações and e or não se aplicam a números diretamente. As operações lógicas


possı́veis entre dois valores numéricos são exibidas na tabela 10:

Operação Operador Expressão


Igual == a == b
Diferente != a != b
Maior > a >b
Menor < a<b
Maior ou igual >= a >= b
Menor ou igual <= a <= b

Tab. 10: Operações lógicas binárias entre números da linguagem Python.

O script a seguir exemplifica as operações da tabela acima:


1 numero = 67
2 outro_numero = -178.54
3 sao_iguais = numero == outro_numero
4 print ( sao_iguais ) # False
5 sao_diferentes = numero != outro_numero
6 print ( sao_diferentes ) # True
7 primeiro_e_maior = numero > outro_numero
8 print ( primeiro_e_maior ) # True
9 primeiro_e_menor = numero < outro_numero
10 print ( primeiro_e_menor ) # False
11 menor_ou_igual = numero <= outro_numero
12 print ( menor_ou_igual ) # False
13 maior_ou_igual = numero >= outro_numero
14 print ( maior_ou_igual ) # True
A operação lógica unária not possui precedência sobre as operações binárias.
Operações lógicas binárias de comparação entre números (==, !=, >, <, >=,
<=) possuem precedência sobre as operações and e or. Se você deseja forçar a
precedência de uma determinada operação lógica binária, tal operação deve ser
escrita entre parênteses, como no exemplo abaixo:
1 resultado = (98 < 89) and ( True and False ) or True
2 print ( resultado ) # True

10 Controlando o fluxo do programa


Cada programa visto nos exemplos desta apostila até então possui um único
fluxo possı́vel de execução. Isto significa que todas as linhas de código do script
10 Controlando o fluxo do programa 19

do programa serão executadas, a menos que ocorra algum tipo de erro durante
a execução do script.
Porém, existem muitos problemas em que desejamos poder controlar o fluxo
de execução do nosso programa, ou seja, controlar quais linhas de código serão
executadas de acordo com uma ou mais condições. Neste caso, o programa terá
mais de um fluxo de execução possı́vel.
Por exemplo, considere o programa que lê a idade do usuário. Digamos que
desejamos customizar a mensagem ao usuário de acordo com a sua idade. Se
o usuário tiver menos de 18 anos, informamos que ele é menor de idade; caso
contrário, informamos que ele já é maior de idade.
Para resolver este problema, utilizaremos as instruções if e else da linguagem
Python. A seguir, o script correspondente:
1 resposta = input ( ’ Digite sua idade : ’)
2 idade = int ( resposta )
3 if idade >= 18:
4 print ( ’ Voc^
e é maior de idade . ’)
5 else :
6 print ( ’ Voc^
e é menor de idade . ’)
A instrução if recebe como argumento um valor booleano. No nosso caso,
passamos como argumento uma expressão lógica, que por sua vez resultará em
um valor booleano. Se este valor for igual a True, então o código delimitado pela
instrução if será executado; caso contrário, o código delimitado pela instrução
else será executado.
É importante “abrir parênteses” nesta seção para falar sobre um assunto
muito importante na programação em Python: identação de código! Observe
este trecho do código do script do exemplo anterior:
1 if idade >= 18:
2 print ( ’ Voc^
e é maior de idade . ’)
Como você já deve ter percebido, a segunda linha está mais à direita em
comparação à primeira linha. De fato, ela possui uma tabulação adicional em
comparação à linha anterior. Isto se deve ao fato de que o código desta linha
pertence ao bloco da instrução if. Assim, ele foi colocado exatamente uma
tabulação à direita (ou mais a dentro) para simbolizar tal fato. Na programação
Python, chamamos este alinhamento de código de identação.
Em Python, a identação de código é obrigatória. Isto significa que, por
exemplo, o código a seguir não será executado:
1 resposta = input ( ’ Digite sua idade : ’)
2 idade = int ( resposta )
3 if idade >= 18:
4 print ( ’ Voc^
e é maior de idade . ’)
10 Controlando o fluxo do programa 20

5 else :
6 print ( ’ Voc^
e é menor de idade . ’)
Ao executar o script acima, o interpretador do Python identificará a instrução
if da terceira linha e, consequentemente, irá verificar que a linha abaixo do if
não está corretamente identada. Assim, ele exibirá na tela a mensagem abaixo:
1 IndentationError : expected an indented block
Ou seja, ele informará que houve um erro e que, no trecho de código onde o
erro foi identificado, era esperado um bloco de código identado.
Fechando os parênteses, voltemos ao assunto principal desta seção. No
exemplo anterior, temos apenas duas situações que são mutuamente exclusivas.
Porém, existem vários problemas os quais necessitam de múltiplas condições para
realizar o roteamento de múltiplos fluxos de execução possı́veis. Como exemplo,
considere o script abaixo, o qual lê a idade do usuário e informa em que faixa de
idade o usuário se encontra:
1 resposta = input ( ’ Digite sua idade : ’)
2 idade = int ( resposta )
3 if idade <= 10:
4 print ( ’ Voc^
e tem menos de 11 anos . ’)
5 elif idade <= 20:
6 print ( ’ Voc^
e tem entre 11 e 20 anos . ’)
7 elif idade <= 30:
8 print ( ’ Voc^
e tem entre 21 e 30 anos . ’)
9 elif idade <= 50:
10 print ( ’ Voc^
e tem entre 31 e 50 anos . ’)
11 else :
12 print ( ’ Voc^
e tem mais de 50 anos . ’)
No exemplo acima, temos cinco condições mutuamente exclusivas, ou seja,
a idade informada pelo usuário irá fazer com que apenas uma condição seja
satisfeita. Assim, não é possı́vel com que o programa execute os trechos de
códigos de duas condições distintas. Para garantir isto, utilizamos a instrução
elif, a qual consiste em uma abreviação das instruções else e if associadas.
Se o usuário digitar uma idade maior que 50, nenhuma das quatro primeiras
condições serão satisfeitas. Isto fará com que o código do bloco da instrução
else seja executado. O bloco else sempre deve ser escrito ao final de todas as
condições, uma vez que ele simboliza o último caso, ou seja, a última opção caso
nenhuma das condições anteriores tenham sido satisfeitas – ou seja, resultado
em True.
Agora, imagine que devemos escrever um programa que simule uma calcu-
ladora simples, capaz de efetuar adições, subtrações, multiplicações e divisões.
O nosso programa funcionará da seguinte forma. Ele solicitará ao usuário dois
10 Controlando o fluxo do programa 21

números reais. Após isto, ele exibirá ao usuário um menu de operações ma-
temáticas a serem realizadas sobre os números que ele informou, conforme abaixo:
1 Digite a operaç~
a o desejada :
2 1 Soma
3 2 Subtraç~ao
4 3 Multiplicaç~
ao
5 4 Divis~ao
Por exemplo, se o usuário deseja multiplicar os dois números que ele informou,
então ele escolherá a opção 3, digitando assim este número no teclado para que
o programa possa enfim realizar a multiplicação dos dois valores. Vamos resolver
este problema utilizando as instruções if, elif e else:
1 resposta = input ( ’ Digite o primeiro número : ’)
2 primeiro_numero = float ( resposta )
3 resposta = input ( ’ Digite o segundo número : ’)
4 segundo_numero = float ( resposta )
5 print ( ’ Digite a oç~ a o desejada : ’)
6 print ( ’1 - Soma ’)
7 print ( ’2 - Subtraç~ a o ’)
8 print ( ’3 - Multiplicaç~ a o ’)
9 print ( ’4 - Divis~ a o ’)
10 resposta = input ( ’ ’)
11 opcao = int ( resposta )
12 resultado = 0
13 resu l t ad o _ ca l c ul a d o = True
14 if opcao == 1:
15 resultado = primeiro_numero + segundo_numero
16 elif opcao == 2:
17 resultado = primeiro_numero - segundo_numero
18 elif opcao == 3:
19 resultado = primeiro_numero * segundo_numero
20 elif opcao == 4:
21 if segundo_numero != 0:
22 resultado = primeiro_numero / segundo_numero
23 else :
24 print ( ’ N~ a o é possı́vel dividir por 0! ’)
25 r e su l t ad o _ ca l c ul a d o = False
26 else :
27 print ( ’ Opç~ a o inválida ! ’)
28 r e su l t ad o _ ca l c ul a d o = False
29

30 if re s u lt a d o _c a l cu l a do :
31 print ( ’ Resultado : % f ’% resultado )
10 Controlando o fluxo do programa 22

O script acima possui uma estrutura de código parecida com a do exemplo


anterior, com exceção ao bloco elif que trata a opção de divisão (opção 4).
Aprendemos nas aulas de matemática que, em uma divisão, o divisor não pode
ser zero. Desta forma, este bloco de código possui um tratamento para verificar
se o divisor, armazenado na variável segundo numero, é diferente de zero, para
assim poder realizar o cálculo da divisão. Caso este tratamento não tivesse sido
feito e o programa executasse uma divisão por zero, o interpretador do Python
lançaria o seguinte erro:
1 ZeroDivis ionErr or : float division by zero
Ou seja, ele lança uma mensagem de erro, informando que houve uma divisão
por zero e consequentemente o programa foi finalizado.
No final do script, existe um bloco if que não faz parte da cadeia de blocos if,
elif e else que faz a verificação da opção do usuário. Este bloco é independente
e verifica se o cálculo do resultado foi realizado com sucesso. Lembrando que
o cálculo é realizado com sucesso quando o usuário digita uma opção válida e,
caso tenha optado pelo cálculo da divisão, o valor do divisor informado não tenha
sido igual a zero.
Condições mutuamente exclusivas do tipo if-else que definem o valor de uma
variável podem ser abreviadas, conforme o exemplo a seguir:
1 from random import randint
2 ’’’
3 A funç~a o randint faz o sorteio
4 de um valor dentre os valores
5 informados como par^ a metro nela
6 ( no nosso exemplo abaixo , entre
7 1 e 11) . A funç~a o randint precisa
8 ser importada do módulo
9 random . Para tanto , usamos a
10 diretiva da linha acima .
11 ’’’
12 numero_aleatorio = randint (1 , 10)
13 paridade = ’ par ’ if numero_aleatorio % 2 == 0 else ’ ı́mpar ’
14 print ( paridade )
No exemplo acima, a função randint faz o sorteio de um valor entre 1 e 10 e
então armazena tal valor na variável numero aleatorio. Em seguida, a variável
paridade recebe a string “par” caso o valor da variável numero aleatorio seja
par ou a string “ı́mpar” caso contrário.
Ainda no exemplo acima, a função randint precisou ser importada do módulo
random para que então pudéssemos usá-la. Para tanto, usamos a diretiva de
importação da primeira linha do script. Ainda veremos nesta apostila outros
scripts que necessitarão importar funções ou módulos para realizar atividades
especı́ficas.
10 Controlando o fluxo do programa 23

Exercı́cios:
(a) Escreva um programa que leia do usuário um número inteiro e então in-
forme na tela se o número é divisı́vel ou não por 7.
(b) Escreva um programa que leia do usuário sua altura (em metros) e seu
peso (em kg), calcule o seu ı́ndice de massa corporal (IMC) e informe na
tela o seu grau de obesidade. O IMC é dado pela fórmula abaixo:

IM C = peso/altura2

A tabela 11 exibe os graus de obesidade referentes a cada faixa de IMC:

Valor IMC Grau de obesidade


<18.5 Abaixo do peso
18.5 ≤ IM C<25 Peso normal
25 ≤ IM C<30 Sobrepeso
30 ≤ IM C<35 Obesidade de grau I
35 ≤ IM C<40 Obesidade de grau II
IM C ≥ 40 Obesidade de grau III

Tab. 11: Graus de obesidade de acordo com o IMC.

(c) Escreva um programa que leia as notas de quatro provas do usuário, calcula
a média das notas. Se a média for maior ou igual a 7, então informe ao
usuário que ele foi aprovado. Se a média for maior que 5 e menor que 7,
informe que ele está de recuperação. Por fim, se a média for inferior a 5,
informe que ele foi reprovado.
(d) Escreva um script que leia do usuário o valor do montante a ser emprestado
e qual o tipo de cliente e então calcule o valor da parcela a ser paga pelo
empréstimo, considerando que as parcelas terão valor fixo e o valor da taxa
para o tipo de cliente. As fórmulas para calcular o valor das parcelas a
serem pagas pelo empréstimo são dadas abaixo:

montante = valor ∗ (1 + ( taxa


100
∗ parcelas))
montante
prestacao = parcelas

onde montante é o valor final do empréstimo com a taxa de juros mensal


aplicada, valor é o valor a ser emprestado, taxa é taxa de juros mensal,
parcelas é a quantidade de parcelas e prestacao é o valor a ser pago em
cada parcela.
A tabela 12 exibe as taxas de juros para cada tipo de cliente:
11 Utilizando laços de repetição 24

Tipo Taxa
de cliente de juros a.m. (%)
Standard 2.5
Platinum 1.99
Gold 1.2

Tab. 12: Taxas de juros para cada tipo de cliente.

11 Utilizando laços de repetição


Imagine que devemos escrever um programa para imprimir na tela a sequência
de 1 até 4 em uma mesma linha. Este problema é extremamente simples e é
resolvido pelo script abaixo:
1 print ( ’1 2 3 4 ’)
Agora, considere que o nosso problema seja criar um programa que leia do
usuário um valor inteiro positivo n e imprima na tela a sequência de 1 até n
em uma mesma linha. Vamos tentar resolver este problema utilizando a mesma
estratégia da solução anterior:
1 resposta = input ( ’ Digite um número inteiro positivo ’)
2 n = int ( resposta )
3 # Garantindo que o valor de n seja positivo :
4 if n < 0:
5 n *= -1
6 elif n == 0:
7 n = 1
8 # E lá vamos nós ...
9 if n == 1:
10 print ( ’1 ’)
11 elif n == 2:
12 print ( ’1 2 ’)
13 elif n == 3:
14 print ( ’1 2 3 ’)
15 elif n == 4:
16 print ( ’1 2 3 4 ’)
17 elif n == 5:
18 print ( ’1 2 3 4 5 ’)
19 elif n == 6:
20 print ( ’1 2 3 4 5 6 ’)
21 # ... continua ... até quando ?

Obviamente, o script acima não consegue resolver o problema de fato, uma


vez que ele só informa a resposta correta para valores de n entre [1..6]. O grande
problema do script acima é que ele não é escalável aos valores de n, ou seja, ele
não consegue resolver o problema para qualquer valor de n. A questão é: como
11 Utilizando laços de repetição 25

saberemos quais os possı́veis valores de n que o usuário poderá digitar? Não há
como saber! Assim, quantas condições lógicas necessitarı́amos para resolver o
problema de fato? Na realidade, infinitas condições!
Desta forma, precisamos escrever um código que seja capaz de imprimir todos
os números da sequência, porém utilizando um número fixo e mı́nimo de linhas
de código. Para tanto, precisamos de alguma forma escrever um código que
repita a impressão dos números de forma categórica e estratégica.
Assim, para realmente resolver este problema, precisamos utilizar um laço
de repetição (ou loop). A linguagem Python oferece dois laços de repetição
distintos: o laço while e o laço for. O script a seguir resolve o nosso problema
utilizando um laço while:
1 resposta = input ( ’ Digite um número inteiro positivo : ’)
2 n = int ( resposta )
3 # Garantindo que o valor de n seja positivo :
4 if n < 0:
5 n *= -1
6 elif n == 0:
7 n = 1
8 contador = 1
9 while contador <= n :
10 print ( contador , end = ’ ’)
11 contador += 1
O laço while recebe como argumento uma condição lógica, chamada de
condição de manutenção do laço. No nosso exemplo, enquanto o valor da
variável contador for menor ou igual ao valor da variável n, o laço while repetirá
a execução do código localizado entre as chaves. No mundo da programação de
computadores, chamamos de iteração cada repetição que um laço realiza.
Note que agora, para qualquer valor de n, a mensagem correta será impressa.
A variável contador é inicializada com o valor 1, que é o primeiro valor que o
nosso programa deve imprimir. A cada iteração, o valor da variável contador é
impresso. Logo em seguida, o valor da variável é incrementado em uma unidade.
Assim, na próxima iteração, o valor a ser impresso é uma unidade maior que o
valor atual.
Note também que utilizamos dentro da função print o parâmetro end com
o valor ‘ ’. O parâmetro end determina o que deve ser impresso sempre ao final
de cada mensagem impressa com a função print. Por padrão, sempre é impresso
o caractere não imprimı́vel \n, o que causa sempre um pulo de linha ao final da
mensagem – e não necessita o uso explı́cito do parâmetro end. Como no nosso
exemplo a função print imprime na tela um número da sequência por vez e a
sequência deve aparecer em uma única linha, modificamos explicitamente o valor
do parâmetro end para ‘ ’, ou seja, um espaço em branco. Assim, os números
11 Utilizando laços de repetição 26

da sequência aparecem separados por um espaço em branco entre eles.


O laço while só é executado se e somente se a sua condição lógica de ma-
nutenção for satisfeita. Assim, para que um laço while execute ao menos uma
iteração, a sua condição lógica de manutenção deve ser satisfeita ao menos uma
vez.
Agora, resolveremos novamente o problema, porém utilizando o laço for:
1 resposta = input ( ’ Digite um número inteiro positivo : ’)
2 n = int ( resposta )
3 # Garantindo que o valor de n seja positivo :
4 if n < 0:
5 n *= -1
6 elif n == 0:
7 n = 1
8 for contador in range (1 , n + 1) :
9 print ( contador , end = ’ ’)
O laço for contém dois argumentos, separados pela palavrada reservada in.
No lado direito, temos um conjunto de valores, sendo que cada um dos valores
deste conjunto será recebido pela variável contador – no lado esquerdo – a cada
iteração.
No nosso exemplo, o conjunto de valores é fornecido pela função range.
Esta função é utilizada para gerar uma sequência de valores. Ela recebe dois
parâmetros. O primeiro parâmetro é o valor inicial da sequência. Por sua vez, o
segundo parâmetro é o valor imediatamente consecutivo após o último valor da
sequência.
Por exemplo, se invocarmos a função range da seguinte forma:
1 range (1 , 6)
Ela retornará a sequência abaixo:
1 [1 , 2 , 3 , 4 , 5]
Ou seja, ela retornou uma sequência cujo primeiro valor é igual ao primeiro
parâmetro informado (1) e o último valor é igual ao valor que antecede o segundo
parâmetro (6). No exemplo anterior do laço for, utilizamos a função range da
seguinte forma:
1 range (1 , n + 1)
Assim, ela retornará a sequência abaixo:
1 [1 , 2 , 3 , ... n ]
Ou seja, uma sequência que inicia com o valor 1 e termina com o valor n
informado pelo usuário.
11 Utilizando laços de repetição 27

O exemplo a seguir lê do usuário um valor positivo n e então imprime uma


sequência de n até 1 em uma mesma linha:
1 resposta = input ( ’ Digite um número inteiro positivo : ’)
2 n = int ( resposta )
3 # Garantindo que o valor de n seja positivo :
4 if n < 0:
5 n *= -1
6 elif n == 0:
7 n = 1
8 for contador in reversed ( range (1 , n + 1) ) :
9 print ( contador , end = ’ ’)
Como a função range é capaz de criar apenas sequências crescentes, utiliza-
mos a função reversed para inverter a sequência gerada pela função range.
É possı́vel utilizar um laço de repetição para percorrer os caracteres de uma
string. O exemplo abaixo insere uma barra vertical (|) entre cada caractere de
uma frase:
1 frase = ’ Ontem eu vi um animal ’
2 for caractere in frase :
3 print ( caractere , end = ’| ’)

Exercı́cios
(a) Escreva um programa que leia do usuário um valor inteiro positivo n e
imprima na tela a sequência:

1, 2, 3, ...n–1, n

Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser


impressa:

1, 2, 3, 4, 5

(b) Escreva um programa que leia do usuário um valor inteiro positivo n e


imprima na tela a sequência:

n − 1, n − 2, n − 3, ...3, 2, 1

Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser


impressa:
11 Utilizando laços de repetição 28

5, 4, 3, 2, 1

(c) Escreva um programa que leia do usuário um valor inteiro positivo n e


imprima na tela a sequência:

[1|2|3|..|n − 1|n − 2]

Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser


impressa:

[1|2|3|4|5]

(d) Escreva um programa que leia do usuário um valor inteiro positivo n e


imprima na tela a sequência:

1, 2, 3, ...n, n − 1, n − 2, ..., 3, 2, 1

Por exemplo, se o valor de n for 5, então a seguinte sequência deverá ser


impressa:

1, 2, 3, 4, 5, 4, 3, 2, 1

(e) Escreva um algoritmo que leia do usuário um valor n entre [1..100] e então
imprima na tela a seguinte sequência:
1 1
2 1, 2
3 1, 2, 3
4 ...
5 1, 2, 3 , ... n 1, n
6 1, 2, 3 , ... n 1
7 ...
8 1, 2, 3
9 1, 2
10 1

Por exemplo, caso o valor n seja 5, a seguinte sequência abaixo deve ser
impressa:
1 1
2 1, 2
3 1, 2, 3
4 1, 2, 3, 4, 5
5 1, 2, 3, 4
6 1, 2, 3
7 1, 2
8 1
12 Listas 29

Caso o valor de n seja 1, então a sequência abaixo deve ser impressa:


1 1

(f) Escreva um programa leia do usuário valores inteiros entre [0..100] até que
o usuário digite o valor -1 e então calcule a média aritmética destes valores
(P.S.: o valor -1 não deve ser incluı́do no cálculo).
(g) Escreva um programa que leia do usuário 10 valores inteiros entre [0..100]
e calcule o produto destes valores.
(h) Escreva um programa que leia do usuário um valor n entre [0..100] e
imprima na tela os primeiros n números da sequência de Fibonacci. Em
uma sequência de Fibonacci, os dois primeiros elementos da sequência são
0 e 1. A partir do terceiro elemento, cada valor é a soma dos dois últimos
valores da sequência anteriores a ele. Como exemplo, a a sequência de
Fibonacci para n igual 8 (ou seja, os oito primeiro elementos da sequência):

0, 1, 1, 2, 3, 5, 8, 13

12 Listas
Todas as variáveis que criamos em nossos exemplos até então possuem a capa-
cidade de armazenamento de apenas um valor por vez. Por exemplo, considere
o script abaixo:
1 numero = 1
2 numero = 2
3 numero = 4
4 numero = -9
5 print ( numero )
Durante a sua execução, o script atribui quatro valores distintos à variável
numero, porém apenas o valor -9 é impresso, pois foi o último valor associado
à variável. Ou seja, não é possı́vel armazenar mais de um valor simultaneamente
na variável numero. O script abaixo exibe uma possı́vel solução a este problema:
1 numero1 = 1
2 numero2 = 2
3 numero3 = 4
4 numero4 = -9
5 print ( numero1 )
6 print ( numero2 )
7 print ( numero3 )
8 print ( numero4 )
12 Listas 30

Neste exemplo, cada valor foi armazenado em uma variável distinta e o valor
de cada variável foi impresso separadamente no final do programa. Note que, se
tivéssemos que armazenar mais valores, terı́amos que criar mais variáveis, além
de mais instruções para exibir tais valores na tela. Desta forma, esta solução
deixa de ser prática à medida que o número de valores aumenta.
Uma solução mais elegante ao problema anterior é utilizar uma lista para
assim poder armazenar vários valores em uma única variável. Listas são estruturas
de dados que representam uma coleção de elementos, onde cada elemento é
representado por uma única chave. O script abaixo apresenta uma possı́vel
solução ao problema anterior, utilizando uma lista para armazenar os valores:
1 numeros = []
2 numeros . append (1)
3 numeros . append (2)
4 numeros . append (4)
5 numeros . append ( -9)
6 for numero in numeros :
7 print ( numero )
Na primeira linha do script, foi criada uma lista vazia. Preste atenção na sin-
taxe de criação desta lista. No código anterior ao sı́mbolo de atribuição (=), foi
declarada uma variável chamada numeros. No código posterior ao sı́mbolo de
atribuição, a variável numeros recebe uma lista vazia, que em Python é expres-
sada por uma abertura de colchetes seguida por um encerramento de colchetes
([]).
A lista é preenchida com quatro números, onde cada número é inserido na
lista por meio da função embutida append. Por fim, os valores da lista são
exibidos em um laço for. Vale a pena neste ponto observar a forma a qual o laço
é utilizado para iterar sobre cada elemento da lista. Na parte direita da palavra
reservada in, foi passada a lista numeros. Na parte esquerda da palavra in, foi
criada uma variável chamada numero, a qual receberá a cada iteração cada um
dos elementos da lista, na ordem em que foram inseridos nela.
No exemplo anterior, os números preenchidos na lista numeros não são
provenientes do usuário, mas sim colocados diretamente no código do script. Em
casos como este, onde já se sabe previamente os valores que uma lista receberá,
é possı́vel preenchê-los de uma vez no momento da criação da lista. O script
abaixo reescreve o script do exemplo anterior, utilizando o preenchimento direto:
1 numeros = [1 , 2 , 4 , -9]
2 for numero in numeros :
3 print ( numero )
Nos dois exemplos anteriores, utilizamos o laço for para exibir um elemento
por vez da lista. Caso deseje imprimir todos os elementos de uma vez, basta
12 Listas 31

imprimir a lista diretamente:


1 numeros = [1 , 2 , 4 , -9]
2 print ( numeros )
No script acima, a função print imprime a seguinte mensagem:
1 [1 , 2 , 4 , -9]
Os elementos de uma lista podem ser acessados da mesma forma que os ca-
racteres de uma string, ou seja, utilizando o mesmo sistema de ı́ndices (positivos
e negativos) que utilizamos com strings. O script abaixo contém alguns exem-
plos de acesso a valores de uma lista e extração de fatias por meio de ı́ndices de
elementos:
1 lista = [10 , 20 , 30 , 40 , 50 , 60 , 70 , 80 ,90]
2 print ( lista [0]) # Imprime 10
3 print ( lista [5]) # Imprime 60
4 print ( lista [ -1]) # Imprime 90
5 print ( lista [0:4]) # Imprime [10 , 20 , 30 , 40]

Os exemplos anteriores exibiram listas de inteiros. É possı́vel criar listas de


todos os tipos de dados que vimos até então nesta apostila. O script abaixo
ilustra algumas listas de tipos variados:
1 numeros_reais = [1.5 , 4.56 , 3.7654 , -0.552]
2 print ( numeros_reais )
3 dias_da_semana = [ ’ Segunda ’ , ’ Terça ’ , ’ Quarta ’ , ’ Quinta ’ , ’ Sexta ’ , ’ Sábado ’ , ’ Domingo ’]
4 print ( dias_da_semana )
5 va lor es_b ool ean os = [ True , True , False , True , False , False ]
6 print ( va lor es_ boo lea nos )
7 # É possı́vel criar listas com elementos de tipos distintos
8 tudo_misturado = [1 , ’ Ontem ’ , False , 3.56]
9 print ( tudo_misturado )

O exemplo a seguir lê do usuário quatro notas de um estudante, calcula a


sua média, verifica se o estudante está aprovado (média maior ou igual a 7),
reprovado (média menor que 5) ou de recuperação (média maior ou igual a 5 e
menor que 7). Caso ele esteja de recuperação, o programa informa qual dentre
as quatro notas que o estudante deve tentar substituir na prova substitutiva para
que então ele seja aprovado:
1 notas = []
2 soma = 0
3 for i in range (0 , 4) :
4 resposta = input ( ’ Digite a ’ + str ( i + 1) + ’. a nota do estudante : ’)
5 nota = float ( resposta )
6 notas . append ( nota )
7 soma += nota
8 media = soma / 4
9 if media >= 7:
10 print ( ’ Estudante aprovado ’)
11 elif media < 5:
12 print ( ’ Estudante reprovado ’)
13 else :
14 menor = 10
15 ordem_nota = 1
16 ordem = 1
17 for nota in notas :
18 if menor > nota :
19 menor = nota
12 Listas 32

20 ordem_nota = ordem
21 ordem += 1
22 print ( ’ Estudante de recuperaç~
a o . ’)
23 print ( ’ Precisa substituir a ’ + str ( ordem_nota ) + ’. a nota para ser aprovado . ’)

Uma breve observação sobre o exemplo acima: utilizamos a função str para
converter os valores numéricos em strings, de tal forma que pudéssemos inseri-los
nas mensagens ao usuário. Execute o exemplo para entender o efeito desejado!
Nos exemplos sobre listas que vimos até agora, vimos algumas operações
com listas, como acesso a elementos, extração de fatias e iteração com laços de
repetição. Veremos a seguir algumas outras operações possı́veis com listas.
O exemplo a seguir lê uma lista de números do usuário até que ele digite
o valor -1 (o qual não é inserido na lista) e então exibe na tela o número de
elementos inseridos na lista e o maior e menor valores existentes nela. Para
tanto, o script utiliza as funções len para calcular a quantidade de elementos da
lista e as funções max e min para encontrar o maior e menor valores dela:
1 numero = 0
2 numeros = []
3 while numero != -1:
4 resposta = input ( ’ Digite um número : ’)
5 numero = int ( resposta )
6 if numero != -1:
7 numeros . append ( numero )
8 quantidade = len ( numeros )
9 maior = max ( numeros )
10 menor = min ( numeros )
11 print ( ’ Quantidade de números inseridos : % d ’% quantidade )
12 print ( ’ Maior número : % d ’% maior )
13 print ( ’ Menor número : % d ’% menor )
O script a seguir simula o sorteio da Mega-Sena. Primeiramente, são sortea-
dos seis números, onde cada número varia de 1 a 60. A cada número sorteado,
o programa verifica se ele já não foi sorteado anteriormente. Após, o programa
solicita ao usuário que informe os seis números da sua aposta. Por fim, o pro-
grama compara os números do usuário com os números sorteados e informa ao
usuário se sua aposta foi vencedora:
1 import random
2

3 numero = random . randint (1 , 60)


4 numeros_s ortead os = [ numero ]
5 for i in range (0 , 5) :
6 while numero in numero s_sort eados :
7 numero = random . randint (1 , 60)
8 nume ros_s ortead os . append ( numero )
12 Listas 33

10 numeros_usuario = []
11 for i in range (0 , 6) :
12 resposta = input ( ’ Digite o ’ + str ( i + 1) + ’. o
número : ’)
13 numero = int ( resposta )
14 numeros_usuario . append ( numero )
15

16 numeros_s ortead os . sort ()


17 numeros_usuario . sort ()
18 print ( ’ Números sorteados : ’)
19 print ( numero s_sort eados )
20 print ( ’ Seus números : ’)
21 print ( numeros_usuario )
22 if num eros_s ortea dos == numeros_usuario :
23 print ( ’ Sua aposta foi vencedora ! ’)
24 else :
25 print ( ’ Infelizmente , sua aposta n~a o foi vencedora . ’)
Para sortear os valores, utilizamos a função randint do módulo random. Esta
função sorteia um número inteiro entre os limites inferior e superior informados
– no exemplo, entre 1 e 60.
No script acima, para evitar que o programa sorteasse números repetidos, in-
serimos um laço while para repetir o sorteio caso o número sorteado já existisse
na lista de números sorteados, utilizando a palavra reservada in para tanto. É
possı́vel comparar duas listas como um todo utilizando o operador ==. Para
que esta comparação funcionasse corretamente no nosso programa, utilizamos a
função embutida sort para ordenar as duas listas antes de realizarmos a com-
paração.
Existem basicamente duas formas de se remover um elemento de uma lista.
A primeira forma consiste em utilizar a função embutida remove, a qual recebe
como parâmetro o elemento a ser removido da lista:
1 lista = [1 , 2 , 3 , 4 , 5]
2 print ( lista ) # [1 , 2 , 3 , 4 , 5]
3 lista . remove (3)
4 print ( lista ) # [1 , 2 , 4 , 5]
A segunda e última forma consiste em utilizar a função embutida pop. Ela
recebe como parâmetro o ı́ndice do elemento a ser removido. Caso nenhum
ı́ndice seja informado, ela remove o último elemento da lista:
1 lista = [1 , 2 , 3 , 4 , 5]
2 print ( lista ) # [1 , 2 , 3 , 4 , 5]
3 lista . pop ()
12 Listas 34

4 print ( lista ) # [1 , 2 , 3 , 4]
5 lista . pop (2)
6 print ( lista ) # [1 , 2 , 4]
O script a seguir exibe um exemplo mais complexo de uso da função remove.
O script realiza o sorteio de dez números inteiros distintos e então os ordena sem
utilizar a função embutida sort (na raça!). Vale a pena parar alguns minutos
para tentar entender o funcionamento deste script!
1 import random
2
3 numeros = []
4 numero = random . randint (1 , 100)
5 numeros . append ( numero )
6 for i in range (0 , 9) :
7 while numero in numeros :
8 numero = random . randint (1 , 100)
9 numeros . append ( numero )
10 print ( numeros )
11 for i in range (0 , 5) :
12 inicio = i
13 fim = 9 - i
14 maior = max ( numeros [ inicio : fim + 1])
15 menor = min ( numeros [ inicio : fim + 1])
16 numeros . remove ( maior )
17 numeros . remove ( menor )
18 numeros = numeros [0 : inicio ] + [ menor ] + numeros [ inicio : fim - 1] + [ maior ] + numeros [ fim - 1:]
19 print ( numeros )

Anteriormente, vimos como extrair uma sub lista de uma lista utilizando a
estratégia de extração de fatias. Também é possı́vel extrair sub listas de forma
categórica. No exemplo a seguir, apenas os números ı́mpares de uma lista de
números são extraı́dos e colocados em outra lista:
1 numeros = [12 , 9 , 87 , -13 , 54 , 78]
2 impares = [ numero for numero in numeros if numero % 2 == 1]
3 print ( impares ) # [9 , 87 , -13]

Na segunda linha do script acima, é realizada uma operação de iteração inline


na lista numeros, selecionando apenas os números da lista que não são divisı́veis
por 2, ou seja, os números ı́mpares.
O script abaixo adiciona uma lista inteira ao final de outra lista. Para tanto,
ele utiliza a função embutida extend:
1 lista1 = [ ’ Ana ’ , ’ Cristiane ’ , ’ Júlia ’ , ’ Luciana ’]
2 lista2 = [ ’ Jo~a o ’ , ’ Carlos ’ , ’ Tiago ’]
3 lista1 . extend ( lista2 )
4 print ( lista1 ) # [ ’ Ana ’, ’ Cristiane ’, ’ Júlia ’, ’ Luciana ’, ’ Jo~
a o ’, ’ Carlos ’, ’ Tiago ’]

Em exemplos anteriores, vimos como utilizar a função embutida append para


inserir um novo elemento em uma lista. Ela insere o novo elemento sempre no
final da lista. Caso seja necessário inserir um novo elemento em uma posição
especı́fica, utilize a função embutida insert, a qual recebe como parâmetro o
ı́ndice do novo elemento a ser inserido e o novo elemento:
1 lista = [ ’ c~a o ’ , ’ gato ’ , ’ canário ’]
2 lista . append ( ’ onça ’)
3 print ( lista ) # [ ’ c~ a o ’, ’ gato ’, ’ canário ’, ’ onça ’]
4 lista . insert (2 , ’ jaguatirica ’)
5 print ( lista ) # [ ’ c~ a o ’, ’ gato ’, ’ jaguatirica ’, ’ canário ’, ’ onça ’]
12 Listas 35

No exemplo do sorteio da Mega-Sena, vimos o uso da palavra reservada


in para verificar se um elemento já existe dentro de uma lista. Caso deseje,
adicionalmente, pegar oı́ndice no qual o elemento está localizado, utilize a função
embutida index para tanto. Lembre-se: a função index assume que o elemento
já existe na lista. Caso ele não exista, a função lança uma exceção (erro). A
seguir, um exemplo de uso da função index:
1 lista = [ ’ c~a o ’ , ’ gato ’ , ’ canário ’ , ’ vaca ’ , ’ cavalo ’]
2 indice_vaca = lista . index ( ’ vaca ’)
3 print ( lista [ indice_vaca ]) # vaca
O script a seguir ordena uma lista em ordem decrescente. Para tanto, ele
ordena a lista de forma crescente, utilizando a função embutida sort e depois
inverte a lista utilizado a função embutida reverse:
1 lista = [ ’ Jo~ a o ’ , ’ Maria ’ , ’ Cecı́lia ’ , ’ Emı́lia ’ , ’ Fernando ’ , ’ Matheus ’ , ’ Ana ’]
2 lista . sort ()
3 lista . reverse ()
4 print ( lista ) # [ ’ Matheus ’, ’ Maria ’, ’ Jo~ a o ’, ’ Fernando ’, ’ Emı́lia ’, ’ Cecı́lia ’, ’ Ana ’]

O script abaixo contabiliza a quantidade de ocorrências da palavra “cão” em


uma lista. Para tanto, ele utiliza a função embutida count:
1 lista = [ ’ c~ a o ’ , ’ gato ’ , ’ canário ’ , ’ vaca ’ , ’ cavalo ’ , ’ c~
a o ’]
2 n r o_o c or r e nc i a s_ c a o = lista . count ( ’ c~
a o ’)
3 print ( n r o _o c o rr e n ci a s _c a o )
Para fechar esta seção, vamos ver um exemplo envolvendo strings. Toda
string em Python possui uma função embutida chamada split, a qual particiona
a string de acordo com a ocorrência de uma determinada sub string. O script
abaixo particiona uma frase de acordo com a ocorrência de cada espaço em
branco. O resultado disso é que a função split quebra a frase original em palavras,
onde cada palavra da frase é um elemento da lista resultante:
1 frase = ’ Estudar programaç~ a o estimula o raciocı́nio lógico ’
2 palavras = frase . split ( ’ ’)
3 print ( palavras ) # [ ’ Estudar ’, ’ programaç~
a o ’, ’ estimula ’, ’o ’, ’ raciocı́nio ’, ’ lógico ’]

Exercı́cios
(a) Escreva um script que crie uma lista de inteiros de tamanho 10, preencha a
lista com valores aleatórios entre [0..100] e exiba a lista em ordem inversa.
(b) Escreva um script que leia do usuário 10 valores inteiros, armazene tais
valores em uma lista e exiba na tela apenas os valores que sejam divisı́veis
por 3.
(c) Escreva um script que leia as notas de 15 alunos e as armazene em uma
lista. Após, o script deve exibir as notas lidas e informar qual foi a nota
média, a maior nota e a menor nota.
13 Dicionários 36

(d) Escreva um script que leia uma frase do usuário e então exiba na tela a
quantidade de palavras que a frase tem. Considere que o usuário pode,
erroneamente, utilizar mais de um espaço em branco entre cada palavra
da frase.

(e) Escreva um script que sorteie 20 valores inteiros, onde cada valor varia
entre [1..10] e então exiba na tela a lista dos valores e o número de vezes
que o número 7 aparece na lista.

(f) Escreva um script que leia do usuário o nome de 10 alunos e suas respecti-
vas médias finais e então exiba na tela os nomes dos alunos que obtiveram
a maior e menor notas.

13 Dicionários
No capı́tulo anterior, aprendemos o que é uma lista e todas as suas operações
básicas. Na Ciência da Computação, dizemos que listas são um tipo de estrutura
de dados, ou seja, são estruturas utilizadas para armazenar e recuperar dados
de forma organizada.
Outra estrutura de dados amplamente utilizada por programadores Python
são os dicionários. Itens de um dicionário são organizados como tuplas, onde
cada tupla é composta por uma chave e um valor. Dentro deste contexto, o
valor corresponde ao dado sendo armazenado e a chave ao ı́ndice do valor.
Para entender o funcionamento de dicionários, observe o exemplo abaixo:
1 copas_ganhas = {}
2 copas_ganhas [ ’ Brasil ’] = 5
3 copas_ganhas [ ’ Itália ’] = 4
4 copas_ganhas [ ’ Argentina ’] = 2
5 print ( copas_ganhas ) # { ’ Itália ’: 4 , ’ Brasil ’: 5 , ’ Argentina ’: 2}

No exemplo acima, criamos o dicionário copa ganhas. Ele é utilizado para


armazenar a quantidade de copas do mundo de futebol ganhas por cada seleção.
Neste exemplo, ele armazena a quantidade de copas ganhas pelas seleções do
Brasil (5), Itália (4) e Argentina (2).
Ou seja, no dicionário copa ganhas, os nomes das seleções correspondem
aos ı́ndices do dicionário e a quantidade de copas ganhas correspondem aos
valores. Assim, é possı́vel recuperar a quantidade de copas ganhas por uma
seleção informando o nome da respectiva seleção. O script abaixo exibe na tela
a quantidade de copas ganhas pela Argentina:
1 copas_ganhas = {}
2 copas_ganhas [ ’ Brasil ’] = 5
3 copas_ganhas [ ’ Itália ’] = 4
4 copas_ganhas [ ’ Argentina ’] = 2
13 Dicionários 37

5 copas_ganhas [ ’ Alemanha ’] = 4
6 print ( copas_ganhas [ ’ Argentina ’ ]) # 2
Quando já sabemos de antemão os valores a serem armazenados em um
dicionário, podemos inicializá-lo com os seus valores. O script abaixo exemplifica
isto:
1 copas_ganhas = { ’ Brasil ’ : 5 , ’ Itália ’ : 4 , ’ Argentina ’ : 2 , ’ Alemanha ’ : 4}
2 print ( copas_ganhas )

Um dicionário também pode ser percorrido por um laço de repetição. Para


tanto, podemos utilizar a função embutida items, conforme o exemplo abaixo:
1 copas_ganhas = { ’ Brasil ’ : 5 , ’ Itália ’ : 4 , ’ Argentina ’ : 2 , ’ Alemanha ’ : 4}
2 for selecao , quantidade in copas_ganhas . items () :
3 print ( ’% s : % d ’ %( selecao , quantidade ) )

Observe que no laço for do script acima foram utilizadas duas variáveis ao
invés de uma única no lado esquerdo da palavra reservada in, ou seja, como
fazemos usualmente. Isto foi necessário pois, a cada iteração, a função items
retorna a chave e o valor de cada item do dicionário.
Assim como as listas, dicionários podem ser utilizados para diversas finalida-
des. O script abaixo lê do usuário uma sequência de números inteiros até que ele
digite o número -1. Após, para cada número distinto que o usuário digitou (com
exceção do número -1), ele informa quantas vezes cada número foi digitado:
1 numero = 0
2 contagem = {}
3 while numero != -1:
4 resposta = input ( ’ Digite um número : ’)
5 numero = int ( resposta )
6 if numero != -1:
7 if numero in contagem :
8 quantidade = contagem [ numero ]
9 contagem [ numero ] = quantidade + 1
10 else :
11 contagem [ numero ] = 1
12 print ( contagem )

No exemplo acima, no trecho mais a dentro do script, é verificado se o


número digitado pelo usuário já é uma chave no dicionário contagem, utilizando
a palavra reservada in para tanto. Caso ele já exista, o seu valor é incrementado
em uma unidade, ou seja, a contagem é incrementada; caso contrário, o número
é adicionado como chave no dicionário e seu valor inicial é 1, para fins de inı́cio
de contagem.
Vimos no exemplo anterior como verificar se uma determinada chave já existe
em um dicionário utilizando a palavra reservada in. Para verificar se uma chave
ainda não existe em um dicionário, é preciso utilizar a palavra reservada not
associada à palavra reservada in, conforme o exemplo abaixo:
13 Dicionários 38

1 cores_roupas = { ’ calça ’ : ’ azul ’ , ’ meias ’ : ’ branco ’ , ’ camiseta ’ : ’ verde ’}


2 if ’ blusa ’ not in cores_roupas :
3 cores_roupas [ ’ blusa ’] = ’ amarelo ’
4 print ( cores_roupas )

Para remover um item de um dicionário, é preciso utilizar a palavra reservada


del, conforme exibido no script abaixo:
1 matriculas = { ’ Jo~a o ’ : ’ 05467 ’ , ’ Maria ’ : ’ 05468 ’ , ’ Alice ’ : ’ 05469 ’}
2 del matriculas [ ’ Maria ’]
3 print ( matriculas ) # { ’ Jo~a o ’: ’05467 ’ , ’ Alice ’: ’05469 ’}

Observação: É importante salientar que é extremamente recomendável que,


antes de se remover um determinado item, seja verificado se a chave do item
existe no dicionário.
Caso deseje remover todos os itens de um dicionário, utilize a função embutida
clear, conforme o exemplo abaixo:
1 matriculas = { ’ Jo~a o ’ : ’ 05467 ’ , ’ Maria ’ : ’ 05468 ’ , ’ Alice ’ : ’ 05469 ’}
2 matriculas . clear ()
3 print ( matriculas ) # {}

É possı́vel criar dicionários de forma dinâmica, utilizando o conceito de dict


comprehension. No exemplo abaixo, é criado um dicionário cujas chaves são
números inteiros entre [1..5] e, para cada item, o seu valor é o quadrado de sua
chave:
1 quadrados = { numero : numero ** 2 for numero in range (1 , 6) }
2 print ( quadrados ) # {1: 1 , 2: 4 , 3: 9 , 4: 16 , 5: 25}

Em algumas situações, é necessário extrair todas as chaves de um determi-


nado dicionário para realizar algum tipo de processamento. Para tanto, basta
utilizar a função embutida keys. O exemplo abaixo extrai as chaves de um
dicionário para percorrer os seus itens:
1 lista_compras = { ’ feij~ a o ’ : 2 , ’ arroz ’: 1 , ’ carne ’ : 3}
2 for chave in lista_compras . keys () :
3 print ( ’% s : % d ’ %( chave , lista_compras [ chave ]) )

Também existem situações em que é necessário extrair apenas os valores de


um dicionário. Para tanto, é preciso utilizar a função embutida values, conforme
exibido no exemplo abaixo:
1 ana = { ’ nome ’ : ’ Ana ’ , ’ idade ’ : 23 , ’ sexo ’ : ’f ’}
2 dados_ana = ana . values ()
3 print ( dados_ana ) # dict_values ([23 , ’f ’, ’ Ana ’])
4 # Convertendo os dados em uma lista com a funç~ a o list
5 dados_ana = list ( dados_ana )
6 print ( dados_ana ) # [23 , ’f ’, ’ Ana ’]
Para ordenar um dicionário de acordo com suas chaves ou valores, é preciso
utilizar a classe OrderedDict do módulo collections. O exemplo abaixo exibe
13 Dicionários 39

como ordenar um dicionário de forma crescente ou decrescente de acordo com


suas chaves ou valores:
1 from collections import OrderedDict
2
3 alunos = { ’ Pedro ’ : 12 , ’ Juliana ’ : 10 , ’ Lucas ’ : 13}
4 # Ordenaç~a o crescente pelas chaves
5 alunos_ordenados = OrderedDict ( sorted ( alunos . items () ) )
6 # OrderedDict ([( ’ Juliana ’, 16) , ( ’ Lucas ’, 13) , ( ’ Pedro ’, 12) ])
7 print ( alunos_ordenados )
8 # Ordenaç~a o decrescente pelas chaves
9 alunos_ordenados = OrderedDict ( sorted ( alunos . items () , reverse = True ) )
10 # OrderedDict ([( ’ Pedro ’, 12) , ( ’ Lucas ’, 13) , ( ’ Juliana ’, 16) ])
11 print ( alunos_ordenados )
12 # Ordenaç~a o crescente pelos valores
13 alunos_ordenados = OrderedDict ( sorted ( alunos . items () , key = lambda item : item [1]) )
14 # OrderedDict ([( ’ Juliana ’, 10) , ( ’ Pedro ’, 12) , ( ’ Lucas ’, 13) ])
15 print ( alunos_ordenados )
16 # Ordenaç~a o decrescente pelos valores
17 alunos_ordenados = OrderedDict ( sorted ( alunos . items () , reverse = True , key = lambda item : item [1]) )
18 # OrderedDict ([( ’ Lucas ’, 13) , ( ’ Pedro ’, 12) , ( ’ Juliana ’, 10) ])
19 print ( alunos_ordenados )

Em algumas situações, cada item de um dicionário pode conter mais de um


valor. Neste caso, o valor do item deve ser uma lista. O exemplo abaixo exibe
este tipo de situação:
1 mamiferos = [ ’ cabra ’ , ’ coelho ’ , ’ gato ’ , ’ vaca ’]
2 peixes = [ ’ pintado ’ , ’ dourado ’ , ’ tucunaré ’]
3 aves = [ ’ pardal ’ , ’ canário ’ , ’ seriema ’ , ’ pombo ’]
4 animais = {}
5 animais [ ’ mamiferos ’] = mamiferos
6 animais [ ’ peixes ’] = peixes
7 animais [ ’ aves ’] = aves
8 ’’’
9 {
10 ’ peixes ’: [ ’ pintado ’, ’ dourado ’, ’ tucunaré ’] ,
11 ’ mamiferos ’: [ ’ cabra ’, ’ coelho ’, ’ gato ’, ’ vaca ’] ,
12 ’ aves ’: [ ’ pardal ’, ’ canário ’, ’ seriema ’, ’ pombo ’]
13 }
14 ’’’
15 print ( animais )

Exercı́cios
(a) Escreva um script que sorteie mil números entre [1..10] e então exiba na
tela quantas vezes cada um dos números foi sorteado.

(b) Escreva um script que sorteie cem números entre [1..10] e então remova
apenas os números que tiveram uma quantidade ı́mpar de ocorrências.

(c) Escreva um script que leia do usuário uma lista de compras, onde para cada
item da compra você deve ler a sua descrição, quantidade e preço unitário.
Os itens da lista devem ser armazenados em um dicionário, utilizando a
14 Manipulação de arquivos 40

descrição de cada item como chave. Após, o script deve calcular o valor
total da compra.

14 Manipulação de arquivos
Todos os programas que escrevemos até então por meio de nossos scripts são
executados em memória primária — no nosso caso, memória RAM (Ran-
dom Access Memory, ou Memória de Acesso Randômico). Porém, quando ma-
nipulamos arquivos programaticamente, estamos trabalhando com dispositivos
de memória secundária, uma vez que arquivos são gravados em dispositivos de
memória não-volátil — ex., HDs, pendrives, etc.
Manipular arquivos programaticamente é uma atividade comum no dia a dia
de desenvolvimento de software. Como um primeiro exemplo, vamos considerar
que desejamos escrever um programa capaz de ler o conteúdo de um arquivo
textual, ou seja, um arquivo composto apenas por caracteres textuais:
1 with open ( ’/ home / sidsu / Documentos / arquivo . txt ’) as arquivo :
2 for linha in arquivo :
3 print ( linha , end = ’ ’)

O script acima utiliza a função open para abrir o arquivo arquivo.txt, o qual
está localizado no diretório /home/sidsu/Documentos. Observe a sintaxe
utilizada para realizar a abertura do arquivo. Utilizamos duas palavras reservadas
da linguagem Python que ainda não tı́nhamos visto nesta apostila: with e as.
Assim, na linha 1 do script abrimos o arquivo arquivo.txt e então o refe-
renciamos utilizando a variável arquivo. No laço for da linha 2, as linhas do
arquivo são lidas sequencialmente, uma linha a cada iteração. Por fim, na linha
3, imprimimos na tela o conteúdo da linha lida. Foi utilizado o parâmetro end
para evitar o pulo de linha adicional na função print, uma vez que a string da
linha lida já contém um pulo de linha em seu final.
Vale a pena salientar que o caminho de um arquivo é composto pelo caminho
desde a raiz da unidade de memória secundária até o diretório onde o arquivo se
encontra, seguido do nome do arquivo. Se o programa estiver sendo executado no
sistema operacional Windows, é preciso substituir cada ocorrência do caractere
’\’ na string do caminho especificado por duas ocorrências do mesmo caractere
(“\\”). Por exemplo, se o arquivo está situado no caminho abaixo:

C:\Users\Sidney\arquivo.txt

Então, a string correspondente para o parâmetro de entrada seria:

“C:\\Users\\Sidney\\arquivo.txt”
14 Manipulação de arquivos 41

Opcionalmente, o mesmo caminho poderia ser definido substituindo-se cada


ocorrência do caractere ’\’ pelo caractere ’/’. Desta forma, o caminho do exemplo
acima ficaria como abaixo:

“C:/Users/Sidney/arquivo.txt”

No último exemplo, realizamos a leitura de um arquivo textual linha a linha.


Alternativamente, podemos ler o conteúdo inteiro de um arquivo textual de uma
só vez utilizando a função read, conforme exibido no exemplo abaixo:
1 with open ( ’/ home / sidsu / Documentos / arquivo . txt ’) as arquivo :
2 print ( arquivo . read () )

Utilizando os conhecimentos que adquirimos nesta apostila, é possı́vel escre-


ver um script para exibir cada palavra de um arquivo textual separadamente. O
script abaixo implementa esta tarefa:
1 with open ( ’/ home / sidsu / Documentos / arquivo . txt ’) as arquivo :
2 for linha in arquivo :
3 for palavra in linha . split ( ’ ’) :
4 palavra = palavra . replace ( ’\ n ’ , ’ ’)
5 palavra = palavra . replace ( ’ , ’ , ’ ’)
6 palavra = palavra . replace ( ’. ’ , ’ ’)
7 palavra = palavra . replace ( ’; ’ , ’ ’)
8 palavra = palavra . replace ( ’: ’ , ’ ’)
9 palavra = palavra . replace ( ’? ’ , ’ ’)
10 palavra = palavra . replace ( ’! ’ , ’ ’)
11 if len ( palavra . strip () ) > 0:
12 print ( palavra )

Antes de aprendermos a gravar conteúdo em um arquivo textual, vamos falar


um pouco sobre a função open. Como dito anteriormente, ela realiza a abertura
de um arquivo existente em algum dispositivo de memória secundária. Para tanto,
a função open recebe como parâmetro o caminho do arquivo a ser aberto.
Porém, além do caminho do arquivo a ser aberto, a função open pode receber
um segundo parâmetro, referente ao modo de acesso a ser utilizado na abertura
do arquivo. O modo de acesso se refere à forma a qual o arquivo será aberto,
sendo que cada forma é baseada em três formas principais: leitura, escrita ou
anexação. A tabela 13 exibe todos os modos de abertura de arquivo da função
open.
14 Manipulação de arquivos 42

Modo Descrição
r Abre um arquivo em modo de leitura somente. O ponteiro do
arquivo é colocado no inı́cio do arquivo. Este é o modo padrão,
sendo utilizado inclusive quando um modo não é informado.
rb Abre um arquivo binário em modo de leitura somente. O pon-
teiro do arquivo é colocado no inı́cio do arquivo. Este é o modo
padrão, sendo utilizado inclusive quando um modo não é infor-
mado.
r+ Abre um arquivo em modo de leitura e escrita. O ponteiro do
arquivo é colocado no inı́cio do arquivo.
rb+ Abre um arquivo binário em modo de leitura e escrita. O ponteiro
do arquivo é colocado no inı́cio do arquivo.
w Abre um arquivo em modo de escrita somente. Se o arquivo
já existir, ele é sobreposto. Caso contrário, um novo arquivo é
criado em modo de escrita.
wb Abre um arquivo binário em modo de escrita somente. Se o
arquivo já existir, ele é sobreposto. Caso contrário, um novo
arquivo é criado em modo de escrita.
w+ Abre um arquivo em modo de leitura e escrita. Se o arquivo
já existir, ele é sobreposto. Caso contrário, um novo arquivo é
criado em modo de leitura e escrita.
wb+ Abre um arquivo binário em modo de leitura e escrita. Se o
arquivo já existir, ele é sobreposto. Caso contrário, um novo
arquivo é criado em modo de leitura e escrita.
a Abre um arquivo em modo de anexação. O ponteiro do arquivo
é colocado no final do arquivo, caso o arquivo já exista. Caso
ele não exista, um novo arquivo é criado em modo de escrita.
ab Abre um arquivo binário em modo de anexação. O ponteiro do
arquivo é colocado no final do arquivo, caso o arquivo já exista.
Caso ele não exista, um novo arquivo é criado em modo de
escrita.
a+ Abre um arquivo em modo de leitura e anexação. O ponteiro do
arquivo é colocado no final do arquivo, caso o arquivo já exista.
Caso ele não exista, um novo arquivo é criado em modo de leitura
e escrita.
ab+ Abre um arquivo binário em modo de leitura e anexação. O
ponteiro do arquivo é colocado no final do arquivo, caso o arquivo
já exista. Caso ele não exista, um novo arquivo é criado em modo
de leitura e escrita.

Tab. 13: Modos de abertura de arquivos da função open.


14 Manipulação de arquivos 43

Veremos a seguir alguns exemplos de escrita, começando com arquivos textu-


ais. O script a seguir grava uma string em um arquivo textual. Caso o arquivo do
caminho e nome especificados já exista, o seu conteúdo antigo será descartado e
o novo conteúdo será gravado. Caso ele ainda não exista, um novo arquivo será
criado dentro do caminho especificado e com o nome especificado:
1 with open ( ’/ home / sidsu / Documentos / saida . txt ’ , ’w ’) as arquivo :
2 arquivo . write ( ’ Este texto será gravado dentro do arquivo . ’)

O exemplo a seguir é bem parecido com o exemplo anterior. Porém, neste


script, caso o arquivo já exista, o novo conteúdo é gravado no final do arquivo.
Caso ele ainda não exista, o comportamento é o mesmo ao do script anterior:
1 with open ( ’/ home / sidsu / Documentos / saida . txt ’ , ’a ’) as arquivo :
2 arquivo . write ( ’ Este texto será gravado no final do arquivo . ’)

Agora, vamos a um exemplo mais complexo. Observe o conteúdo do arquivo


notas.txt abaixo:
1 7.8
2 9.2
3 7
4 8.45
O script a seguir abre o arquivo notas.txt, faz a leitura das quatro notas
existentes no arquivo, calcula a média aritmética das notas e então grava a
média calculada no final do arquivo:
1 with open ( ’/ home / sidsu / Documentos / notas . txt ’ , ’a + ’) as arquivo :
2 soma = 0
3 contador = 0
4 arquivo . seek (0)
5 for linha in arquivo :
6 nota = float ( linha )
7 soma += nota
8 contador += 1
9 media = soma / contador
10 arquivo . write ( ’\ n ’ + str ( media ) )

Vimos até então como manipular arquivos textuais, ou seja, arquivos cujo
conteúdo é composto unicamente por caracteres textuais. Por sua vez, um
arquivo binário possui uma estrutura mais complexa, podendo conter outros
tipos de dados além de caracteres. Exemplos de arquivos binários são arquivos
de imagens (ex., JPEG, PNG), de áudio (ex., MP3, OGG), vı́deo (ex., MP4,
AVI), documentos do MS Office (ex., DOC, XLS), entre outros.
Quando lemos o conteúdo de um arquivo binário, não estamos lendo uma
string de caracteres, como ocorre na leitura de um arquivo textual, mas sim uma
string de bytes. Para entender do que se trata uma string de bytes, vamos
recordar um pouco sobre strings de caracteres, isto é, as string que já estamos
acostumados nessa apostila. Observe o exemplo abaixo:
14 Manipulação de arquivos 44

1 frase = ’ Eu sou uma string . ’


2 print ( frase [0]) # E
No exemplo acima temos uma string de caracteres na variável frase. Na
segunda linha do script, imprimimos o conteúdo do caractere doı́ndice 0 da string,
respectivamente o caractere ’E’. Nada demais do que já estamos acostumados.
Agora, observe o exemplo abaixo:
1 frase = b ’ Eu sou uma string . ’
2 print ( frase [0]) # 69
Este último exemplo é muito parecido com o exemplo anterior, porém a
variável frase está recebendo a string de caracteres com um prefixo b. Isto
faz com que a string de caracteres seja convertida em uma string de bytes, onde
cada elemento desta string de bytes corresponde ao respectivo caractere da string
original, convertido para o seu valor inteiro em bytes correspondente.
Voltando a falar sobre arquivos binários, vimos na tabela 13 que existem
modos especı́ficos para a abertura de arquivos binários (modos com sufixo ’b’).
Como um primeiro exemplo, o script abaixo imprime na tela todos os bytes de
um arquivo de imagem:
1 with open ( ’/ home / sidsu / Imagens / imagem . png ’ , ’ rb ’) as arquivo :
2 byte = arquivo . read (1)
3 while byte != b ’ ’:
4 print ( byte [0] , end = ’ ’)
5 byte = arquivo . read (1)

Pare ler cada byte do arquivo por vez, utilizamos a função embutida read,
passando como parâmetro o valor 1 sinalizando que queremos ler apenas um
byte. O laço while é utilizado para repetir a leitura dos bytes até o último byte
do arquivo. Após ler o último byte do arquivo, quando a função read tenta
realizar uma nova leitura, ela retorna o valor b”, o qual simboliza que não há
mais bytes a serem lidos. Desta forma, o laço while termina sua execução.
Vejamos agora um exemplo mais útil. O script abaixo utiliza a mesma es-
tratégia do exemplo anterior para realizar a cópia de um arquivo de imagem.
Para realizar a gravação do byte lido do arquivo fonte no arquivo de destino, ele
utiliza a função embutida write:
1 with open ( ’/ home / sidsu / Imagens / imagem . png ’ , ’ rb ’) as fonte :
2 with open ( ’/ home / sidsu / Imagens / imagem2 . png ’ , ’ wb ’) as destino :
3 byte = fonte . read (1)
4 while byte != b ’ ’:
5 destino . write ( byte )
6 byte = fonte . read (1)

Opcionalmente, podemos ler todo o conteúdo de um arquivo de uma só vez.


Porém, é importante ressaltar que esta estratégia deve ser utilizada com cautela,
haja visto que todo o conteúdo do arquivo é trazido para a memória principal
14 Manipulação de arquivos 45

de uma só vez, o que pode ser custoso dependendo do tamanho do arquivo e
a quantidade de memória principal disponı́vel no sistema operacional. O script
abaixo realiza a cópia de um arquivo de imagem, utilizando esta estratégia:
1 with open ( ’/ home / sidsu / Imagens / imagem . png ’ , ’ rb ’) as fonte :
2 with open ( ’/ home / sidsu / Imagens / imagem2 . png ’ , ’ wb ’) as destino :
3 byte = fonte . read ()
4 destino . write ( byte )

Nos exemplos anteriores, vimos como realizar a leitura e escrita em arquivos


textuais e binários. Tais operações são muito úteis e possuem diversas aplicações.
Porém, às vezes precisamos realizar atividades que exigem apenas a leitura dos
metadados de arquivos ou diretórios, não precisando necessariamente realizar
operações de leitura e escrita.
Metadados são basicamente ”dados sobre dados”. No contexto de arquivos
e diretórios, temos metadados como o nome do arquivo, seu diretório, seu ta-
manho, se ele é um arquivo ou diretório, entre outros. A seguir, veremos alguns
exemplos básicos sobre manipulação de metadados de arquivos.
O exemplo a seguir utiliza a função isfile do módulo os.path para verificar
se um determinado caminho se refere a um arquivo, retornando True caso sim
ou False caso contrário. O exemplo também utiliza a função isdir de forma
análoga para verificar se o caminho se refere a um diretório:
1 from os . path import isfile , isdir
2
3 eh_arquivo = isfile ( ’/ home / sidsu / Documentos / arquivo . txt ’)
4 print ( eh_arquivo ) # True
5 eh_pasta = isdir ( ’/ home / sidsu / Documentos / arquivo . txt ’)
6 print ( eh_pasta ) # False

O exemplo a seguir exibe o uso da função basename do módulo os.path


para pegar o nome de um arquivo a partir do caminho de seu diretório:
1 from os . path import basename
2
3 nome_arquivo = basename ( ’/ home / sidsu / Documentos / arquivo . txt ’)
4 print ( nome_arquivo ) # arquivo . txt

Neste próximo exemplo, é solicitado ao usuário que informe o caminho de


um diretório. Após, o script utiliza a função listdir do módulo os para pegar os
nomes de todos os arquivos e diretórios existentes dentro do diretório informado:
1 from os import listdir
2 from os . path import isdir
3
4 diret orio_ra iz = input ( ’ Digite o caminho do diretório raiz : ’)
5 if isdir ( diretori o_raiz ) :
6 for arquivo in listdir ( di retorio_ raiz ) :
7 print ( arquivo )
8 else :
9 print ( ’O caminho informado n~ a o se refere a um diretório . ’)

Agora, imagine que desejamos escrever um script que lê do usuário o cami-
nho de um diretório e então contabiliza a quantidade de arquivos e diretórios
14 Manipulação de arquivos 46

existentes do diretório informado. Iremos implementar duas soluções para este


problema. A primeira solução usa a função join do módulo os.path para obter
o caminho de cada item existente dentro do diretório informado, podendo assim
verificar se o item é um arquivo ou diretório:
1 from os import listdir
2 from os . path import isdir , join
3
4 diret orio_ra iz = input ( ’ Digite o caminho do diretório raiz : ’)
5 if isdir ( diretori o_raiz ) :
6 quantidade_arquivos = 0
7 quantidade_diretorios = 0
8 for arquivo in listdir ( di retorio_ raiz ) :
9 arquivo = join ( diretorio_raiz , arquivo )
10 if isdir ( arquivo ) :
11 q u a n t i d a d e _ d i r e t o r i o s += 1
12 else :
13 q u a n t i d a d e _ a r q u i v o s += 1
14 print ( ’ Nro de diretórios : % s ’% q u a n t i d a d e _ d i r e t o r i o s )
15 print ( ’ Nro de arquivos : % s ’% q u a n t i d a d e _ a r q u i v o s )
16 else :
17 print ( ’O caminho informado n~ a o se refere a um diretório . ’)

Como um último exemplo sobre manipulação de metadados de arquivos, o


script abaixo utiliza a função getsize do módulo os.path para pegar o tamanho
em bytes de um arquivo:
1 from os . path import getsize
2
3 tamanho = getsize ( ’/ home / sidsu / Documentos / arquivo . txt ’)
4 print ( tamanho )
Agora, como um último exemplo geral sobre arquivos, o script a seguir realiza
a remoção de um arquivo e um diretório, utilizando as funções remove e rmdir
do módulo os. Lembre-se de tomar muito cuidado quando implementar scripts
que realizam a remoção de arquivos ou diretórios!
1 from os import remove , rmdir
2
3 remove ( ’/ home / sidsu / Documentos / arquivo . txt ’)
4 rmdir ( ’/ home / sidsu / Documentos / diretorio ’)

Exercı́cios
(a) Escreva um script que leia o caminho de um diretório do usuário e então
informe a quantidade de arquivos para cada extensão de arquivo encontrada
dentro do diretório.
(b) Escreva um script que seja capaz de ler o arquivo entrada.txt, o qual
contém as notas dos alunos de uma determinada turma. O arquivo é
estruturado da seguinte forma:
15 Lidando com erros 47

1 NUMERO_ALUNOS NUMERO_NOTAS
2 NOTA1_ALUNO1 NOTA2_ALUNO1 NOTA3_ALUNO1 ...
3 NOTA1_ALUNO2 NOTA2_ALUNO2 NOTA3_ALUNO2 ...
4 NOTA1_ALUNO3 NOTA2_ALUNO3 NOTA3_ALUNO3 ...

Por exemplo, a versão abaixo do arquivo exemplo.txt contém as 4 notas


de 5 alunos:
1 5 4
2 7.6 6 8.89 10
3 5 4.2 3.37 7
4 10 9.8 8.7 9.2
5 7 6 8 7
6 2.1 2.2 3 4.1

Após realizar a leitura do arquivo exemplo.txt, o programa deve realizar o


cálculo da média aritmética das notas de cada aluno e gravar os resultados
no arquivo saida.txt, o qual deve ser estruturado da seguinte forma:
1 NUMERO_ALUNOS
2 MEDIA_ALUNO1
3 MEDIA_ALUNO2
4 MEDIA_ALUNO3
5 ...

Por exemplo, o conteúdo do arquivo saida.txt correspondente ao arquivo


exemplo.txt do exemplo anterior seria o seguinte:
1 5
2 8.1225
3 4.8925
4 9.425
5 7
6 2.85

15 Lidando com erros


Bem, se você chegou até aqui, espero que você tenha lido todas as seções
anteriores, testado os exemplos, realizado os exercı́cios e aprendido os princı́pios
básicos de programação de computadores utilizando a linguagem Python. Caso
sim, meus parabéns!
Porém, não posso deixar você sair por aı́ escrevendo scripts Python sem antes
falar de um assunto extremamente importante: tratamento de erros!
Mas antes, vamos definir o que é um erro. Dentro do contexto de pro-
gramação de computadores, existem basicamente dois tipos de erros: os sintáticos
e os semânticos.
15 Lidando com erros 48

Os erros sintáticos são erros que ocorrem quando a sintaxe da linguagem de


programação utilizada na escrita do programa não é obedecida. Por exemplo, o
script a seguir possui um erro sintático. Você consegue encontra-lo?
1 numero = 2
2 if numero % 2 == 0
3 print ( ’ Par ’)
Bem, se você observou cuidadosamente o script acima, deve ter percebido
que está faltando o sinal de dois pontos (:) no final da instrução if. Se tentarmos
executar este script, a saı́da será esta:
1 File " exemplo01 . py " , line 2
2 if numero % 2 == 0
3 ^
4 SyntaxError : invalid syntax
Para fazer com que este erro não seja mais informado, basta corrigir o erro
sintático ocorrido, colocando o sinal de dois pontos no final da instrução if. De
fato, para corrigir qualquer tipo de erro sintático, basta realizar a devida correção
no código fonte do script.
Por sua vez, erros semânticos são mais complicados de se corrigir. Eles podem
ocorrer por duas situações básicas. A primeira situação ocorre quando temos um
erro na nossa lógica de programação. Por exemplo, observe o script a seguir:
1 somatorio = 0
2 numero = 0
3 while numero != -1:
4 resposta = input ( ’ Digite um número : ’)
5 numero = int ( resposta )
6 if numero != -1:
7 somatorio = numero
8 print ( ’ Somatório dos numeros : % d ’% somatorio )
O script acima deveria realizar a leitura de um conjunto de números inteiros
do usuário até que ele digitasse o número -1 e então calcular o somatório dos
números do usuário (com exceção do número -1). Apesar de não possuir erros
sintáticos, o script não realiza o somatório corretamente. Vou deixar para você
a tarefa de encontrar o erro semântico deste script!
A segunda situação ocorre quando a nossa lógica de programação está cor-
reta, porém acontece algo inesperado durante a execução do programa. Tal
situação pode ocorrer por diversos motivos, como por exemplo uma entrada
inválida do usuário. Observe o script a seguir:
1 resposta = input ( ’ Digite um número : ’)
2 numero1 = int ( resposta )
15 Lidando com erros 49

3 resposta = input ( ’ Digite outro número : ’)


4 numero2 = int ( resposta )
5 resultado = numero1 + numero2
6 print ( ’% d + % d = % d ’ %( numero1 , numero2 , resultado ) )
Não é difı́cil entender que o script acima realiza a leitura de dois números
inteiros do usuário e então exibe na tela a soma dos dois números. Para tanto,
nas linhas 2 e 4, as respostas do usuário são convertidas para valores inteiros para
que assim a soma possa ser feita posteriormente. Porém, e se ao invés de digitar
um número inteiro, o usuário digitasse um número real com casas decimais? O
resultado disso é exibido abaixo:
1 Digite um número : 1.2
2 Traceback ( most recent call last ) :
3 File " exemplo03 . py " , line 2 , in < module >
4 numero1 = int ( resposta )
5 ValueError : invalid literal for int () with base 10: ’ 1.2 ’

Na saı́da acima, o usuário digitou o valor 1.2 para o primeiro número. Ime-
diatamente, o interpretador do Python lançou um erro chamado ValueError,
informando que o valor 1.2 é inválido para a conversão pela função int.
Toda vez que o interpretador do Python detecta um erro semântico deste
tipo, ele interrompe a execução do script. Isto é uma situação muito embaraçosa
para o usuário, uma vez que ele não espera que este tipo de erro aconteça.
Mas a questão é: como tratar um erro inesperado deste tipo? Bem, basta
tratar o erro colocando o código passı́vel de erro dentro de um bloco try, captu-
rando o tipo de erro possı́vel com a instrução except. Abaixo, alteramos o script
do exemplo anterior para tratar o possı́vel erro de entrada inválida do usuário:
1 numero1 = 0
2 numero_lido = False
3 while not numero_lido :
4 try :
5 resposta = input ( ’ Digite um número : ’)
6 numero1 = int ( resposta )
7 numero_lido = True
8 except ValueError :
9 pass
10 numero2 = 0
11 numero_lido = False
12 while not numero_lido :
13 try :
14 resposta = input ( ’ Digite outro número : ’)
15 numero2 = int ( resposta )
16 numero_lido = True
15 Lidando com erros 50

17 except ValueError :
18 pass
19 resultado = numero1 + numero2
20 print ( ’% d + % d = % d ’ %( numero1 , numero2 , resultado ) )
No exemplo acima, quando o usuário digitar um valor inválido, o interpre-
tador lançará o erro ValueError. Porém, desta vez, o erro será interceptado
pelo código do script, graças à instrução except. No caso, toda vez que esta
interceptação ocorrer, a instrução pass fará com que o erro seja ignorado e o
código continue a sua execução, repetindo a leitura do número até que o usuário
digite um número inteiro.

Referências
[1] BEAZLEY, D.; JONES, B. K. Python Cookbook. O’Reilly Novatec, 2013.

[2] Python Software Foundation. Python 3.5.1 documentation, 2016. Disponı́vel


em https://docs.python.org/3/. Acessado em 23 de maio de 2016.

[3] tutorials point. Python - Tutorial, 2016. Disponı́vel em http://www.


tutorialspoint.com/python/. Acessado em 23 de maio de 2016.

Vous aimerez peut-être aussi