Instruções: Enquanto você lê, você deve acompanhar os exemplos utilizando um console Python. Experimente escrever outras instruções análogas e vá além do que está escrito. Após a leitura do conteúdo abaixo, você deve ler os capítulos 1, 2 e o capítulo 3 até 3.1.2 do tutorial Python.
Estruturas elementares em Python
Suponha que precisamos somar dois números de vários algarismos, digamos, 124682 e 2468. Esses números são pequenos, então você pode facilmente escrever os dois números no papel, alinhados pelo último dígito, e executar um algoritmo de soma tradicional.
124682 + 2468 -------- 127150
Melhor ainda, para esse problema pode ser razoável tomar uma calculadora de mesa. Uma calculadora nada mais é do que um computador que realiza operações aritméticas e em que escrevemos as instruções diretamente no teclado. Se quisermos utilizar um computador moderno, então precisamos decidir duas coisas:
- Em que linguagem de programação escreveremos nossas instruções?
- Qual o mecanismo utilizaremos para executar essas instruções?
A resposta da primeira pergunta para essa disciplina é Python 3. Como Python é uma linguagem interpretada, a resposta da segunda pergunta é invocando um interpretador. Existem duas maneiras de invocar o interpretador do Python: interativa e não interativa.
Interpretador de comandos interativo
Usamos o interpretador de comandos interativos quando queremos
realizar operações simples e curtas apenas uma vez. Muitas vezes
também utilizamos esse interpretadora para experimentar e explorar a
linguagem, algum algoritmos ou alguma biblioteca de funções existente.
Para isso, primeiro invocamos o interpretador de comandos python3
sem argumentos a partir do terminal do computador.
python3
Iremos ver o console do Python 3 em que podemos digitar comandos, como
Python 3.7.3 (default, Oct 7 2019, 12:56:13) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
Podemos digitar expressões aritméticas usuais (soma, subtração, divisão e multiplicação) nesse console. Experimente várias delas.
>>> 124682 + 2468 127150
Ao contrário do computador moderno, a nossa calculadora é bem limitada. Você deve adivinhar que uma das principais limitações da calculadora é que a memória dela é muito limitada — só armazena os operandos e, normalmente, um resultado anterior. Se você tiver realizando operações com várias números, você precisa anotar cada resultado intermediário no papel. Em Python, podemos criar uma variável. Por exemplo, o IMC é dado pela seguinte fórmula
$$ \mbox{IMC} = \frac{{\mbox{massa}}}{({\mbox{altura}}\cdot {\mbox{altura}})} $$
Então podemos calcular nosso índice como o seguinte
>>> peso = 73 >>> altura = 1.75 >>> imc = peso / (altura * altura) >>> imc 23.836734693877553
Devemos ler "peso recebe 73", "altura recebe 1.75", etc. O que as três primeiras linhas fazem é criar variáveis que guardam os valores do lado direto. Lembrem-se, uma variável corresponde a uma caixa na memória que guarda um determinado valor. Cada uma dessas três linhas faz o seguinte:
- reserva um espaço na memória suficiente para um valor
- guardo o valor do lado direito de
=
nesse espaço - associa o nome do lado esquerdo de
=
a esse valor
Observe que apenas após a último linha obtemos algum resultado: atribuição não é uma expressão em Python e apenas expressões têm o seu valor impresso no console interativo.
Tipos de variáveis
Você deve se lembrar de que todo valor armazenado na memória do computador tem um tipo associado. Para descobrir o tipo associado a cada uma das variáveis, usamos o seguinte:
>>> type(peso) <class 'int'> >>> type(altura) <class 'float'> >>> type(imc) <class 'float'>
Vemos que peso
tem tipo int
. Um tipo int
corresponde a um número
inteiro (positivo, negativo ou zero). Em Python 3 (mas não em Python
2), um número inteiro pode ter quantos dígitos forem necessários.
Experimente, por exemplo, calcular a décima potência de -99999999
em uma
calculadora comum. Certamente ela terminará com um erro. Em Python,
podemos fazer o seguinte
>>> -99999999 ** 10 -99999990000000449999988000000209999997480000020999999880000000449999999000000001
Você acabou de aprender que **
corresponde ao operador de
exponenciação de Python. Mas tem algo estranho: a potência par de um
número não pode ser negativa, mas o resultado obtido foi negativo! Na
verdade, o que acabamos de calcular foi -(99999999 ** 10)
. O
operador **
tem precedência ou prioridade sobre o operador de
negação -
. Deveríamos escrever, portanto,
>>> (-99999999) ** 10 99999990000000449999988000000209999997480000020999999880000000449999999000000001
Já as variáveis altura
e imc
têm tipo float
. Um float
é um
tipo numérico de ponto flutuante, que é utilizada para guardar uma
aproximação de um número real. Observe que falamos ponto, e não
vírgula: ao contrário do português do Brasil, na maioria das
linguagens de programação utilizamos um ponto .
para indicar a parte
fracionária de um número.
O fato de que guardamos uma aproximação ao usarmos um número
fracionário é importante. Por exemplo, é evidente que a soma
0.1 + 0.2
deve valer exatamente 0.3
, mas o interpretador Python
parece discordar:
>>> 0.1 + 0.2 0.30000000000000004
Ao contrário dos números inteiros, em que sempre guardamos uma representação exato no número, não é possível guardar uma representação exata de cada número real. Pense, por exemplo, em como representar o número $\pi$ e cada um dos outros números irracionais: não podemos enumerar todos os números irracionais! Para a maioria das nossas aplicações que veremos, usar uma aproximação é mais do que suficiente, mas devemos tomar cuidado sempre que:
- compararmos números de ponto flutuante
- armazenarmos números astronomicamente grandes ou pequenos
As variáveis de ponto flutuante são armazenadas guardando três números inteiros: sinal, mantissa e expoente e representam um número $$(-1)^{sinal} \cdot mantissa \cdot 2^{expoente}$$
Por exemplo, $$0.5 = (-1)^0 \cdot 1 \cdot 2^{-1}$$
Para a programadora, normalmente é indiferente essa representação, desde que ele se atente ao fato de que cada número de ponto flutuante é uma aproximação de algum número representado!
É claro que o tipo da variável peso
é inteiro, pois o valor atribuído
é 73
. Podemos forçar a utilização de float
adicionando um ponto
>>> peso_float = 73. >>> type(peso_float) <class 'float'>
Mas por que imc
tem tipo float
? O motivo disso é que a expressão
do lado direito é avaliada para um número float: sempre que dividimos
dois números, obtemos um float em Python 3, mesmo que a divisão seja
exata! Se quisermos obter apenas o quociente inteiro de uma divisão,
usamos o operador //
>>> 5 / 2 2.5 >>> 6 / 2 3.0 >>> 6 // 2 3
Erros
Quando programamos pode acontecer uma série de erros. Um dos erros mais comuns é o erro de sintaxe e pode acontecer mesmo com operações bem simples como as que aprendermos. Por exemplo, se nos esquecermos de um operador
>>> imc = peso / (altura altura) File "<stdin>", line 1 imc = peso / (altura altura) ^ SyntaxError: invalid syntax
O símbolo ^
está apontando para o elemento do programa (token) que
não era esperado naquela posição. De fato, ali deveríamos ter um símbolo
de multiplicação *
.
Outro erro de programação bastante comum é utilizar uma variável não definida, algumas vezes porque escrevemos o nome da variável com a grafia incorreta
>>> imc = peso / (altura * autura) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'autura' is not defined
Outros erros são chamados erros de execução e acontecem apenas no momento da execução. Por exemplo, se tivéssemos digitado a altura erradamente:
>>> peso = 73 >>> altura = 0 >>> imc = peso / (altura * altura) Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
Os erros acima são chamados de exceções. Quando uma exceção ocorre, o interpretador para a execução do seu programa com uma mensagem de erro e se recursa a continuar. Algumas vezes, é preciso tratar exceções, mas por agora não falaremos disso. Nos nossos primeiros programas, as exceções indicam simplesmente que o programa está incorreto é deve ser corrigido.
Finalmente, podemos ter erros de lógica, que são erros que não são detectados pelo interpretadores. Ao contrário dos erros anteriores, pode ser difícil encontrar esse erro e, algumas vezes, um erro de lógica pode passar desapercebido por muito tempo. Já vimos esse problema com a precedência acima. Vamos ver outro caso de descuido com a ordem das operações:
>>> peso = 73 >>> altura = 1.75 >>> imc = peso / altura*altura >>> imc 73.0
Alguém que tomasse esse resultado como correto iria com certeza estar bastante preocupado com sua saúde!
Um parênteses: módulos
Uma razão comum para se usar uma sessão interativa do interpretador é
experimentar com novos módulos e funções. Não vamos ver como criar módulos agora,
mas podemos desde já como utilizá-los. Suponha que queremos calcular a raiz
quadrada de um número. Não existe operador em Python dedicado para isso,
mas podemos importar esse operador de um módulo math
. Por exemplo,
para calcular o tamanho da diagonal de um retângulo, fazemos o seguinte:
>>> import math >>> cateto1 = 10 >>> cateto2 = 5 >>> hipotenusa = math.sqrt(cateto1**2 + cateto2**2) >>> hipotenusa 11.180339887498949
Dica: nas sessões interativas, as teclas para cima e para baixo
navegam no histórico de comandos digitados. Além disso, você pode usar
o tab para completar uma palavra, depois de escrever o prefixo. Por
exemplo, para ver quais nomes ou operadores estão disponíveis no
módulo importado, digite math.
e aperte tab duas vezes. Para ver o
que cada operação faz, use help
: help(math.cos)
irá mostrar a
documentação dessa operação. Talvez seja necessário digitar q
para
sair da documentação.
Escrevendo um programa
Embora o modo interativo do interpretador Python seja útil, ele só serve em situações limitadas, quando queremos executar as instruções uma única vez. Na maior parte das vezes, quando queremos executar instruções Python, primeiro escrevemos um programa em Python. Os programas em Python também são chamados de script, em parte porque Python é utilizado muitas vezes com ferramenta de automação de tarefas cotidianas, em parte para distinguir de outros programas já compilados em linguagem de máquina.
Vamos construir um programa que
- pede para o usuário digitar um nome
- imprime uma mensagem de bom dia para o usuário
Criamos o seguinte programa, i.e., criarmos um arquivo
de texto chamado bomdia.py
e digitamos
usuario = input("Digite seu nome: ") print("Bom dia", usuario)
Após salvar o arquivo, podemos executar o programa invocando o interpretador Python em um terminal de execução. Esse programa irá imprimir uma mensagem pedindo o nome. Ao escrevermos algum texto, digamos, Maria, e apertarmos Enter, obteremos o seguinte terminal
user@host:$ python3 bomdia.py Digite seu nome: Maria Bom dia Maria
No programa vemos dois comandos que fazem parte da Linguagem Python. A
função input
lê um texto digitado pelo usuário no teclado até o
momento em que ele digita a tecla Enter. O que essa função devolve é
uma variável que guarda a sequência de caracteres digitada pelo
usuário. Essa variável, que é do tipo string, ou str
, é associada ao
identificador usuario
, que é o nome do usuário.
A função print
recebe uma sequência de argumentos, cada um pode ter
um valor e um tipo diferente. O que ela faz é mostrar (ou imprimir) na
tela os valores na forma de texto, isso é, de uma string. Se houver
vários argumentos, a função print
irá mostra um espaço entre eles.
Strings
No código acima, temos "Bom dia"
que é uma string literal. As
strings literais representam valores do tipo str
que não mudam e
correspondem à sequência de caracteres entre as aspas. Se quisermos
inserir um caractere de aspas dentro da string, precisamos escapar do
significado especial que esse caractere tem utilizando uma
contra-barra, ou backslash antes.
Por exemplo, considere um programa pensamento.py
com o seguinte
conteúdo
frase = "Descartes disse:\n\"penso, logo existo\"" print(frase)
O primeiro comando de pensamento.py
cria uma string com aspas.
Poderíamos também utilizar aspas simples,
frase = 'Descartes disse:\n"penso, logo existo"' print(frase)
já que o caractere "
não têm significado especial dentro da string
literal. Se executarmos esse programa, iremos obter
Descartes disse: "penso, logo existo"
Repare que o \n
não foi impresso, mas sim foi mostrada uma quebra de
linha: de fato, \n
é um caractere de controle que instrui o terminal
a saltar uma linha. Se quiséssemos a própria barra, deveríamos escapar
do significado especial da barra, usando
frase = 'Descartes disse:\\n"penso, logo existo"' print(frase)
que imprimiria
Descartes disse:\n"penso, logo existo"
Operações de string
Assim como podemos fazer operações com números inteiros e números de ponto flutuante, também podemos fazer várias operações com string. Uma operação comum é criar uma substring ou acessar um determinado caractere. Veja o exemplo:
frase = "O essencial é invisível aos olhos" print("O primeiro caractere é: ", frase[0]) print("O segundo é um espaço: ", frase[1]) print("A segunda palavra é: ", frase[2:11]) print("Um sufixo é:", frase[16:]) print("A última palavra é:", frase[-5:])
Executando o código acima, obtemos
O primeiro caractere é: O O segundo é um espaço: A segunda palavra é: essencial Um sufixo é: visível aos olhos A última palavra é: olhos
Execute o exemplo, releia o código e reflita. Procure entender porque essa saída é executada e procure a documentação se necessário.
Uma outra operação comum com strings é a concatenação. Por exemplo, poderíamos reescrever o exemplo acima da seguinte maneira; dessa vez, usando a pontuação adequadamente.
usuario = input("Digite seu nome: ") mensagem = "Bom dia, " + usuario + "." print(mensagem)
Reutilizamos o símbolo de +
. Mas perceba que nesse caso ambos
operandos são strings, assim o significado de +
é concatenar as
duas strings, em ordem. Qual a saída será obtida?
Convertendo tipos
Vamos agora usar o que aprendemos para criar um programa que calcula a hipotenusa de um triângulo retângulo. Escrevemos o seguinte
import math cateto1 = input() cateto2 = input() hipotenusa = math.sqrt(cateto1*cateto1 + cateto2*cateto2) print("A hipotenusa é " + hipotenusa)
Como você já deve imaginar, esse programa não funciona. Experimente. O
motivo é fácil de entender: ninguém garante que o usuário irá escrever
dois números válidos! E de fato, input
apenas lê uma sequência de
caracteres e não tenta interpretá-la de nenhuma maneira. O tipo de
ambos cateto1
e cateto2
no programa acima é str
. Ou seja, são
strings: não podemos multiplicar
duas strings!
Para que nosso programa funcione, precisamos que o valor das variáveis
que representam os catetos sejam números de ponto flutuante! Mas como
transformar uma string, que contém a sequência de dígitos decimais e, possivelmente um ponto, no número fracionário que ele representa em
ponto flutuante? Para isso, usamos uma função de conversão
para float
.
import math cateto1 = float(input()) cateto2 = float(input()) hipotenusa = math.sqrt(cateto1*cateto1 + cateto2*cateto2) print("A hipotenusa é " + hipotenusa)
Agora sim, a hipotenusa será calculada corretamente! Mas o programa
ainda está incorreto. O erro é que tentamos fazer uma concatenação com
um operando que não é uma string! Para converter um valor em uma
string, usamos a função str
. Corrija esse programa usando conversão
para string e depois fazendo a concatenação adequada!
Formatando a saída
Em Python 3, existe uma maneira bem conveniente de converter valores em strings, que são as strings de modelo para formatação. A ideia é escrever um texto e deixar marcações, placeholders, para substituir com o valor formatado. Por exemplo, se quiséssemos sempre escrever o valor da hipotenusa com duas casas decimais, poderíamos fazer o seguinte
import math cateto1 = float(input()) cateto2 = float(input()) hipotenusa = math.sqrt(cateto1*cateto1 + cateto2*cateto2) print("Os catetos são {} e {}!".format(cateto1, cateto2)) print("A hipotenusa é {:0.2f}.".format(hipotenusa))
Procure na documentação as várias formas de usar format
. Nas versões
mais novas de Python, há também uma maneira mais compacta
de escrever esse código, usando as f-strings:
import math cateto1 = float(input()) cateto2 = float(input()) hipotenusa = math.sqrt(cateto1*cateto1 + cateto2*cateto2) print(f"Os catetos são {cateto1} e {cateto2}!") print(f"A hipotenusa é {hipotenusa:0.2f}.")
Repare que as f-strings começam com um símbolo f
.
Comandos condicionais
Vamos resolver o seguinte exercício:
Escreva um programa que lê um número inteiro do teclado e imprime "sim" se o número for par e maior do que 10, ou for ímpar e menor do que 50. Caso contrário o programa deve imprimir "não".
Primeiro, vamos tentar escrever um algoritmo em português
numero <-- leia um número do teclado se número for par se numero > 10 imprima sim senão imprima não do contrário, se for ímpar se numero < 50 imprima sim senão imprima não
Parece razoável supor que esse problema é bem simples, então fazendo algumas simulações rápidas nos convencemos de que o programa está correto. Vamos reescrever o algoritmo, agora em Python
numero = int(input()) if numero % 2 == 0: if numero > 10: print("sim") else: print("não") else: if numero < 50: print("sim") else: print("não")
Há muitas novidades aqui, vamos parte a parte. Primeiro, o recuo em
que os comandos são escritos é fundamental para identificar a
estrutura do algoritmo. Temos duas palavras-chaves novas: if
e
else
. O comando if
significa se e é seguido por uma condição.
Se essa condição for verdadeira, e somente nesse caso, o corpo de
comandos que segue os dois pontos e que está recuado é executado. O
comando else
é opcional; o corpo desse comando é executando sempre
que o a condição do if
falhar.
Valores booleanos
Primeiro precisamos entender o que é uma condição: uma condição é uma
expressão cujo resultado é um valor do tipo bool
. Um tipo bool
,
por sua vez, é um valor de verdade que pode ser ou True
ou False
e
nada mais.
Obtemos valores booleanos normalmente fazendo perguntas! Em uma linguagem de programação, essas perguntas estão na forma de comparações e outras funções. Por exemplo, se quisermos verificar se o usuário digitou apenas números decimais, podemos usar
numero_string = input() if numero_string.isdigit(): numero = int(numero_string) print(f"O texto digitado {numero_string} contém apenas dígitos decimais.") else: print(f"O texto digitado {numero_string} contém apenas dígitos decimais.")
Poderíamos reescrever o programa anterior da seguinte maneira:
numero = int(input()) par = numero % 2 == 0 maior_10 = numero > 10 menor_50 = numero < 50 if par: if maior_10: print("sim") else: print("não") else: if menor_50: print("sim") else: print("não")
O tipo dessas três novas variáveis é bool
. Confira usando um console
Python e digitando
var = True type(var) par = numero % 2 == 0 type(var)
Operadores booleanos
Às vezes, queremos fazer duas perguntas ao mesmo tempo, outras vezes precisamos satisfazer apenas uma de várias condições. Pensando nisso, vamos reescrever o programa
numero = int(input()) par = numero % 2 == 0 maior_10 = numero > 10 menor_50 = numero < 50 if par and maior_10: print("sim") elif not par and menor_50: print("sim") else: print("não")
Observamos algumas novas palavras-chaves: a primeira é and
(a
conjunção e escrita em inglês) que significa que queremos que
ambas condições sejam verdadeiras, a da esquerda e a da direita; a
segunda é not
(não em inglês), que nega o valor e verdade de uma
expressão; a última é elif
, que significa, do contrário, verifique a
condição e execute. O elif
nada mais é do que uma forma mais
compacta de escrever um código equivalente:
numero = int(input()) par = numero % 2 == 0 maior_10 = numero > 10 menor_50 = numero < 50 if par and maior_10: print("sim") else: if par and menor_50: print("sim") else: print("não")
Mas, como essa sequência de if
seguido de else
é bastante comum,
fica mais fácil escrever todos os corpos de comando no mesmo recuo.
Podemos usar quantos elif
após um if
quanto forem necessários.
No nosso exemplo, o corpo de if
e elif
são iguais. Assim, podemos
simplificar ainda mais o programa acima.
numero = int(input()) par = numero % 2 == 0 maior_10 = numero > 10 menor_50 = numero < 50 if par and maior_10 or not par and menor_50: print("sim") else: print("não")
A palavra-chave or
é um operador que devolve verdadeiro bastando que
pelo menos um dos seus operando seja True
.
Note que nem sempre é fácil entender qual a ordem em que as operações
serão executadas. Para isso é necessário conhecer a precedência dos
operadores (e um bocado de experiência). No caso do if
acima, not
é executado primeiro e or
é executado por último. Em expressões
complicadas, como a acima, é sempre mais claro (e mais prático), usar
parênteses:
numero = int(input()) par = numero % 2 == 0 maior_10 = numero > 10 menor_50 = numero < 50 if (par and maior_10) or (not par and menor_50): print("sim") else: print("não")
O nome booleano, que em Python corresponde a bool
, é uma homenagem a
um matemático
George Bool, a quem é
frequentemente atribuída a criação da álgebra booleana. Por ora, basta
conhecermos bem as chamadas tabelas-verdades das operações:
A |
not A |
---|---|
True | False |
False | True |
A |
B |
A and B |
---|---|---|
True | True | True |
True | False | False |
False | True | False |
False | False | False |
A |
B |
A or B |
---|---|---|
True | True | True |
True | False | True |
False | True | True |
False | False | False |
Relembrar algumas equivalências bem conhecidas também é importante:
not (a == b)
é equivalente aa != b
not (a != b)
é equivalente aa == b
not (a > b)
é equivalente aa <= b
not (a < b)
é equivalente aa >= b
not (a >= b)
é equivalente aa < b
not (a <= b)
é equivalente aa > b
E refletir sobre algumas formas que às vezes passam desapercebido:
not (a and b)
é equivalente anot a or not b
not (a or b)
é equivalente anot a and not b
Repetindo
O corpo de comandos de if
e de else
pode ser executado uma ou
nenhuma vez dependendo da condição. Muitas vezes, queremos repetir um
conjunto de comandos enquanto determinada condição é satisfeita.
Iremos ver comandos repetitivos com calma depois. Por enquanto, resolvamos um exercício:
Escreva um programa que leia ma sequência de pares de números inteiros e pare apenas quando a soma de ambos for 42.
print("Escreva dois números") a = int(input()) b = int(input()) soma = a + b while soma != 42: print("Escreva dois números") a = int(input()) b = int(input()) soma = a + b print(f"Parabéns, a soma de {a} e {b} é um número fundamental")
Há uma novidade: a palavra-chave while
é como if
, mas é um comando
repetitivo, isso significa que o corpo de comandos do while
deve
mudar o valor das variáveis a mudar a expressão de condição.
Há um problema desse código: repetimos a mesma coisa duas vezes. Como sempre precisamos executar uma vez, podemos substituir a expressão da condição por uma variável, assim:
procurando = True while procurando: print("Escreva dois números") a = int(input()) b = int(input()) soma = a + b if soma == 42: procurando = False print(f"Parabéns, a soma de {a} e {b} é um número fundamental")