0% acharam este documento útil (0 voto)
4 visualizações71 páginas

Tutorial Básico de Programação em Python

Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
4 visualizações71 páginas

Tutorial Básico de Programação em Python

Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Tutorial Básico sobre a

Linguagem Python
??/??/2021

PET - Tecnologia em Eletrônica e Computação


Universidade Federal de Itajubá - UNIFEI

Itajubá Minas Gerais


1

Introdução
Neste tutorial será apresentado os conceitos básicos da linguagem de programação
Python. Não é necessário possuir nenhum conhecimento prévio em outras linguagens de
programação.

Python é uma linguagem de alto nível criada com o intuito de ser uma linguagem
simples de se aprender, fácil de ler e concisa. Foi criada em 1992 por Guido van Rossum e
desde então é desenvolvida de forma comunitária com a liderança da Python Software
Foundation.

É uma linguagem interpretada, ou seja, o código é executado linha a linha por um


interpretador, isso permite uma rapidez em testar e corrigir programas. Python também
possui tipagem dinâmica, o que permite que variáveis no programa possam mudar de tipo
durante a execução do programa.

Configurando o ambiente
Para este tutorial será utilizado a plataforma online [Link] que pode ser encontrada
no seguinte site: [Link] Ao acessar a página deve-se clicar em start coding. Em
seguida será pedido que você crie uma conta, faça isso e siga os passos que o próprio site
fornece. Na hora de escolher as linguagens deve-se escolher a linguagem python e mais
outras duas de sua preferência, pois o site exige que se escolha ao menos três. No meu
caso ficou como na figura a seguir:
2

Em seguida será pedido que você verifique sua conta e faça uma introdução sobre
você mesmo, mas isso é opcional. Para os objetivos deste tutorial você deve selecionar a
opção Python logo após a linha “or start coding” como indicado na próxima figura.
3

Você será levado para uma nova página destinada a programação em Python.
No painel mais à esquerda são mostrados os nomes dos arquivos que estão sendo
editados. Ao abrir pela primeira vez provavelmente haverá apenas o arquivo [Link]. No
painel do meio é a área de edição, onde pode-se escrever ou modificar o código Python.
Por fim, no painel mais à direita fica o terminal contendo o REPL da linguagem e também
onde aparecem os resultados da execução do programa.
4

REPLs são utilizados para executar pequenos comandos da linguagem, geralmente


com o propósito de realizar testes simples. O leitor pode experimentar digitar alguma
expressão simples no REPL, como por exemplo “2 + 2” e pressionar a tecla Enter.

> 2 + 2
4

Hello World
Na programação é comum que ao se iniciar o aprendizado de alguma linguagem o
primeiro programa escrito seja um “Hello World”, e é exatamente isso que será realizado
neste tutorial. O programa em Python pode ser escrito da seguinte forma:

print("Hello world")
5

Escreva isso no painel de edição de texto, o do meio. Em seguida pressione o botão


Run localizado na barra superior da página. Se tudo ocorrer bem a mensagem Hello World
deverá aparecer no painel à direita, isto é, no REPL.

Para facilitar a leitura do código pode-se adicionar comentários ao código que serão
ignorados pelo interpretador. Para isso deve-se usar o símbolo # em alguma posição da
linha, tudo escrito entre esse símbolo e o final da linha será considerado um comentário.
# Isso é um comentário
print("Oi amigo") # Outro comentário
# Isso também é um comentário

Variáveis
Uma das coisas mais básicas que um programa de computador deve ser capaz de
realizar é armazenar e modificar valores em memória. Para isso é feito uso das chamadas
variáveis. Uma variável pode ser criada em Python a partir do seguinte código:

a = 15
print(a)

No trecho de código cria-se uma variável chamada a e atribui-se a ela o valor 15. Na
linha seguinte usa-se o comando print para exibi-la. O nome de uma variável pode ter
qualquer comprimento desde que comece com uma letra, ou _, e não utilize nenhum
símbolo não alfanumérico. valor, rato1, grafenó, Aphex_Twin e x_ são exemplos de
nomes válidos. pão quadrado, 123gameplays, tatu#mola? e pula-pula exemplos de
nomes inválidos.

A partir da linha em que se declara uma variável é possível modificar o seu valor,
veja a seguir.

var1 = 15
print(var1)
var1 = 23
print(var1)
var1 = var1 + 1
print(var1)
6

Nesse último exemplo declara-se a variável var1 com o valor 15, exibe-a, altera-se
seu valor para 23 e a exibe novamente. Na linha seguinte, var1 = var1 + 1, a variável é
modificada tal que seu novo valor é o valor antigo somado de 1, ou seja, 24. Lembrando
que só se pode usar uma variável do lado direito do sinal de atribuição(=) se a mesma tiver
sido declarada anteriormente.

Também pode-se declarar variáveis com valores não numéricos como, por exemplo,
texto. Esses valores de texto devem ser escritos entre aspas simples ou duplas e são
chamados de strings.

b = "Hello World"
print(b)

No trecho acima é apresentado uma forma alternativa do programa Hello World, em


vez de usar diretamente a string no comando print, salva-a primeira em uma variável que
depois é passada para o comando.

Trabalhando com Números


Em Python existem dois tipos principais de números, inteiros e reais. Os inteiros,
chamados como ints na linguagem, são representados por números sem casas decimais
como no exemplo a seguir.

a = 12
b = 123432
c = 99999

Já os números reais, também chamados de ponto flutuante ou floats, são escritos


com casas decimais. Deve-se usar o ponto e não a vírgula para separar a parte inteira da
fracionária. Alguns exemplos são:

a = 12.3
b = 0.6
c = 0.0000001

Entre números e variáveis contendo números, diversas operações matemáticas são


suportadas.

a = 5 + 7 # soma
b = 3.5 - 1 # subtração
c = a * 10 # multiplicação
d = b/2 # divisão
7

e = 5//2 # divisão inteira


e = 2 ** 64 # exponenciação
f = 5 % 2 # resto da divisão

Tentar realizar uma operação matemática entre tipos não numéricos causará um
erro e o programa não será executado.

a = "oi"
b = 1
c = a + b # causa um erro

Trabalhando com Strings


Como mencionado anteriormente, strings são valores que representam texto. Esse
tipo de dado suporta também algumas operações como, por exemplo, o operador + pode
ser utilizado para concatenar (unir) strings.

nome = "Zbigniew"
sobre_nome = "Preisner"
nome_completo = nome + sobre_nome
print(nome_completo)

Ao executar esse código será exibido ZbigniewPreisner tudo junto. Isso ocorre
porque ambas as strings foram simplesmente unidas sem um espaço entre elas. Para
contornar esse problema, pode-se modificar a terceira linha para

nome_completo = nome + " " + sobre_nome

Às vezes também pode ser necessário converter um valor numérico para string e
vice-versa. Para isso é muito simples, basta usar os comandos int() float() e str().

Para converter um valor inteiro ou real para string:

inteiro = 12
versao_texto = str(inteiro)
print("o numero é " + versao_texto)

Na segunda linha a variável versao_texto recebeu o valor de inteiro convertido


para string. Dessa forma pode-se concatenar essa variável com a string "o numero inteiro é"
sem problemas, o que não poderia ser feito diretamente com a variável inteiro. É
importante ressaltar que o comando str() não modifica a variável original apenas cria
8

uma cópia de seu valor convertido para string. Por isso, mesmo após e execução do
comando str(), a variável inteiro continua com um valor do tipo numérico.

O contrário também é válido, pode-se converter uma variável de tipo string para um
valor inteiro ou real.

var1 = "12"
var2 = "23.1"

a = int(var1)
b = float(var2)

print(a + b)

Para converter uma string para inteiro usa-se o comando int() e uma string para
real, float(). Uma string só pode ser convertida para um desses valores se ela contiver
um texto que represente um número, caso contrário será gerado um erro.

a = "123/3"
b = "2321a"
c = "zero"

x = float(a) # Erro
y = int(b) # Erro
c = int(c) # Erro

Interpolação de Strings
O operador “%” pode ser usado para realizar interpolação de strings. Representa uma
forma alternativa a concatenação para compor variáveis, constantes e strings em uma
nova string. Durante a interpolação símbolos especiais dentro da string são substituídos
por valores indicados entre parênteses após o operador “%”. Por exemplo:

nome = "Krzysztof Penderecki"


nacionalidade = "polonês"
nascimento = 1933
# o símbolo "\" pode ser usado para dividir a linha, quando a mesma é muito
# longa
frase = "%s é um famoso compositor %s nascido em %d" % \
(nome, nacionalidade, nascimento)
print(frase)
9

Observe ao executar o código que o primeiro símbolo “%s” dentro da string foi substituído
pela string na variável nome, a primeira indicada entre os parênteses. Da mesma forma o
segundo símbolo “%s”. Já o símbolo “%d” foi substituído pelo valor inteiro da terceira
variável convertido para string.
Os símbolos disponíveis para substituição são os seguintes:
● %s: string
● %d: inteiro
● %o: inteiro em formato octal
● %x: inteiro em formato hexadecimal
● %f: números de ponto flutuante
● %e: números em notação científica
● %%: caso queira inserir o sinal de porcentagem.

F-Strings
Uma alternativa a interpolação de strings são as F-Strings. São semelhantes as
strings literais porém, seguem o formato f”conteúdo” em vez de “conteúdo”. Ao se colocar o
nome de uma variável entre chaves dentro do conteúdo de uma F-String seu valor é
convertido para string e inserido na mesma. Por exemplo:
nome = "Krzysztof Kieślowski"
nacionalidade = "polonês"
obra = "Trilogia das cores"
frase = f"{nome} é um famoso cineasta {nacionalidade} conhecido pela obra \
{obra}"
print(frase)

Entrada de Dados
Uma outra tarefa muito importante que os programas de computador devem
realizar é a leitura de dados inseridos pelo usuário. Para isso existe o comando input()
que ao ser executado pausa o programa e exibe uma mensagem pedindo que seja digitado
algo. Após ser digitado e ser pressionado Enter o comando retornará uma string contendo
o que foi digitado. Um exemplo deixará mais claro:

a = input("digite algo")
print("Eu digitei isso: " + a)

Após iniciar a execução desse programa, no terminal será exibido a mensagem


"digite algo". Por exemplo, digite "privada polonesa giratória" e pressione Enter. O
10

programa terminará sua execução e será exibido a mensagem "Eu digitei isso: privada
polonesa giratória".

O próximo exemplo estima o ano de nascimento do usuário baseado em sua idade.

idade_str = input("digite sua idade")


idade_int = int(idade_str)
ano_nascimento = 2020 - idade_int
print("Você nasceu em " + ano_nascimento)

Observe que como o valor retornado por input() é uma string, é necessário
convertê-lo para um tipo inteiro antes de usá-lo em uma expressão matemática. Também
vale ressaltar que se o usuário digitar um valor não numérico o programa irá ser abortado
com um erro.

Expressões Booleanas
Expressões booleanas são expressões cujo valor resultante é verdade ou falso. Por
exemplo, a expressão a seguir gera um valor falso, pois 2 não é maior que 4.

2 > 4

Em Python valores falsos são representados pela palavra chave False e os


verdadeiros por True. Várias operações podem ser realizadas sobre esses valores.

● and
○ Resulta em verdadeiro se ambos os operandos são verdadeiros, falso caso
contrário.
● or
○ Resulta em falso se ambos operandos são falsos, verdade caso contrário.
● not
○ Inverte o valor do operador.

Operadores relacionais também geram valores booleanos:

operador descrição
11

> Maior que

< Menor que

>= Maior ou igual que

<= Menor ou igual que

== Igual

!= Diferente

A seguir alguns exemplos do uso desses operadores na linguagem.

a = True and False # Resulta em a = False


b = True or False # Resulta em b = True
c = 2>4 # Resulta em c = False
d = True and (5>3) # Resulta em d = True
e = False == True # Resulta em =e False

Condicionais

if e else
Em certos casos pode querer-se executar um trecho de código apenas quando uma
certa condição for satisfeita. Para isso se faz uso das expressões condicionais através das
palavras-chave if e else.

if 2 > 4:
print("2 é maior que 4")

No código acima a segunda linha só será executada se a expressão booleana após o


if for verdadeira. Nesse caso nada será executado pois 2 não é maior que quatro.

a = 12
if a == 12:
print("a é igual a 12")
12

Nesse outro exemplo, a linha 3 só será executada se a variável a for igual a 12, o
que é verdade nesse caso. Logo, a mensagem “a é igual a 12” será exibida. Lembrando que,
para realizar-se comparação de igualdade, deve-se usar dois sinais de igual, isto é, ==.

Todo o código que será executado pertencente ao if deve estar indentado em


relação ao comando, ou seja, deve-se adicionar um carácter Tab. Por isso o código a seguir
apresenta um erro.

a = "zig"
if a == "zig":
print("zag")

No próximo exemplo as linhas 3 e 4 só serão executadas se x for negativo, e a


última linha será executada independentemente do if.

x = -10
if x < 0:
x = -x;
print("módulo de x é " + str(x))
print("Essa linha é sempre executada")

Em outras ocasiões pode ser útil ter um trecho de código que só será executado se
a expressão no if não for verdadeira. Para isso faz-se uso da palavra-chave else. Importante
ressaltar que para todo else deve haver um if.

x = int(input("digite um número "))


if x % 2 == 0:
print("x é par")
else:
print("x é ímpar")

Nesse exemplo é verificado se x é ímpar ou par. Para isso, lê-se x como um número
digitado pelo usuário e no if é verificado o resultado do resto da divisão de x por 2. Se for 0,
quer dizer que o número é par, caso contrário o código do bloco else será executado,
indicando que o número é ímpar.

elif
Outra palavra chave importante é elif que representa uma condição alternativa ao if,
um exemplo deixará mais claro.

idade = int(input("digite sua idade "))


if idade < 20:
13

print("VOCÊ É MOLEQUE!")
elif idade < 40:
print("você é adulto")
elif idade < 90:
print("você é velho")
elif idade < 120:
print("nossa...")
else:
print("para de mentir")

O trecho de código funciona da seguinte forma. Primeiro a variável é lida como uma
entrada do usuário. Em seguida, na linha 3, é verificado se o valor de idade é menor que 20.
Caso seja, a linha 3 é executada e o programa se encerra. Caso não seja verdade, na linha 5
é verificado se é menor que 40. Se for menor, então a próxima linha é executada e o
programa se encerra, caso contrário, passa-se ao elif seguinte e assim por diante. Caso
nenhum dos elifs sejam satisfeitos então o else será executado.

Laços de Repetição
Outra funcionalidade básica que uma linguagem de programação deve fornecer é a
capacidade de que um mesmo código possa ser executado repetidas vezes. Os principais
tipos de laços são o while e o for.

while
O laço while executa repetidamente um trecho de código enquanto uma expressão
booleana for verdadeira. No exemplo a seguir, a variável x é exibida enquanto seu valor for
menor que 10.

a = 0
while a < 10:
print(a)
a = a + 1
print("fim")

Quando a execução do código atinge pela primeira vez a linha a 3, é verificado se a


é menor que 10. Isso é verdade, então o bloco de código pertencente ao while é executado.
Ao se chegar ao final do bloco, a execução do programa retorna para a linha 3 e verifica
novamente se a é menor que 10. Mais uma vez é verdade, o corpo do while é executado e
retorna à linha 3, e assim sucessivamente. Quando a é igual a 10 a verificação falha e a
execução ignora o corpo do while indo direto para a linha 7.
14

for
O laço for é parecido com o laço while, porém ele é utilizado, de forma simplificada,
para um número fixo de repetições. Ele é formado pela palavra chave for seguido de um
nome uma variável, palavra chave in e o comando range.

for a in range(10):
print(a)

Nesse trecho, a linha 2 é executada 10 vezes com a assumindo os valores 0, 1, 2, 3,


4, 5, 6, 7, 8 e 9 (o 10 não faz parte) a cada repetição.

É possível também indicar diferentes faixas de valores para a modificando o range().

for a in range(12):
print(a) # a assume valores de 0 a 11
for a in range(3, 10):
print(a) # a assume valores de 3 a 9
for a in range(4, 13, 2):
print(a) # a assume valores de 4 a 12, porém de 2 em 2.

No exemplo abaixo é feito um programa que soma 4 números digitados pelo


usuário.

soma = 0
for x in range(4):
valor = float(input("digite um número: "))
soma += valor
print("A soma é " + str(soma))

break
Em algumas ocasiões pode-se querer sair de uma laço antes que o mesmo termine.
Para isso é usado a palavra-chave break. A seguir um exemplo de um programa que exibe a
raiz de um número digitado pelo usuário caso este seja positivo e caso contrário o
programa interrompe a sua execução.

while True:
a = float(input("Entre com com um número: "))
if a < 0:
break
else:
15

print(a**0.5)

Escopos
Um conceito muito importante em linguagens de programação é o de escopo. O
papel dele é indicar, basicamente, onde pode-se utilizar uma variável declarada. Considere
o seguinte exemplo.

a = 12
if True:
print(a)

Observe que a foi declarado fora de qualquer tipo de estrutura como if ou for.
Nesse caso pode-se usar a variável em qualquer lugar do programa, pois ela foi declarada
no que é conhecido como Escopo Global. Porém observe o próximo exemplo.

if True:
a = 12
print(a)

Esse código resultará em um erro, pois a foi declarada em um escopo interno e está
tentando usá-la no escopo global. Porém a variável poderia ser utilizada em um escopo
mais interno:

if True:
a = 12
for i in range(4):
print(a)

A variável foi declarada em um escopo interno, porém foi utilizada em um escopo


mais interno ainda, logo, nesse caso não há problema.

Listas
Muitas vezes pode ser útil ter a capacidade de representar um conjunto de valores
em uma única variável. Para isso existem as listas, que consistem em vários valores entre
colchetes e separados por vírgula.

lista1 = [1, 2, 3, 4]
lista2 = ["oi", "meu", "chapa"]
16

lista3 = ["beringela", "maionese", 12.3, True]

print(lista1)
print(lista2)
print(lista3)

Para acessar um único elemento de uma lista faz-se uso de índices, isto é, o nome
da variável seguido de um número entre colchetes. Este número indica a posição do
elemento que se quer acessar. Ressaltando que a posição começa a ser contada a partir do
zero.

lista1 = [10, 8, 3, 12]

a = lista1[0] # acessa o primeiro elemento


b = lista1[1] # acessa o segundo
c = lista1[3] # acessa o quarto elemento

Pode-se usar também um número negativo como índice, nesse caso, a contagem
ocorre de trás para frente com -1 sendo o último elemento.

compras = ["leite", "tomates", "cebola", "ceifadeira de cabine dupla"]

a = compras[-1] # acessa o último


b = compras[-2] # acessa o penúltimo
c = compras[-3] # acessa o antepenúltimo

Também é possível modificar listas de forma semelhante a variáveis.

compras = ["leite", "tomates", "cebola", "ceifadeira de cabine dupla"]

compras[0] = "suco"
compras[1] = "beterraba"
compras[2] = "batata"
compras[-1] = "curso de guerrilha"

print(compras)

Um comando muito útil que pode ser utilizado sobre listas é o len que retorna a sua
quantidade de itens. Com ele é possível percorrer listas da seguinte forma:

compras = ["leite", "tomates", "cebola", "ceifadeira de cabine dupla"]

for i in range(len(compras)):
print("Na posição " + str(i) + " temos o elemento: " + compras[i])
17

Na linha 3 len(compras) retorna o tamanho da lista que nesse caso é 4. Logo a


variável do for, i, assumirá os valores de 0 a 3 que serão utilizados para acessar os
elementos da lista.

O laço for também pode ser usado para percorrer os elementos de uma lista
diretamente.

lista = [4, 2, 1, 3]

for a in lista:
print(a)

Nesse exemplo a cada repetição a variável a assume um dos valores da variável lista
em ordem, nesse caso, 4, 2, 1 e 3.

Na realidade, a única coisa que o comando for faz é iterar sobre os elementos de
uma lista. O range, apresentado na seção anterior, não faz nada além de criar uma lista de
números. Experimente digitar o seguinte no REPL da linguagem:

list(range(10))

Isso resultará em uma lista dos números de 0 até 9.

Exemplos
O programa do exemplo a seguir soma todos os elementos de uma lista de inteiros.

lista = [67, 68, 69, 70, 71, 72, 73, 75, 77, 79, 83, 87, 88, 94]
soma = 0
for i in lista:
soma += i
print(soma)

Já o trecho de código a seguir verifica se duas listas de mesmo tamanho são iguais.

listaA = [5, 1, 2, 4]
listaB = [5, 1, 2, 4]
iguais = True

for i in range(len(listaA)):
if listaA[i] != listaB[i]:
iguais = False
break
18

if iguais == True:
print("As listas são iguais")
else:
print("As listas são diferentes")

No trecho, a variável iguais indica se as listas são iguais, e inicialmente ela foi
definida como True. No laço for, a cada iteração, a variável i assume um dos valores de 0
até 3 e o usa para acessar uma dada posição das listas e compará-las. Caso uma das
comparações resulte em falso, a variável iguais assume o valor False e o laço é
interrompido. Já quando todas as comparações são verdadeiras, o laço é completado e
iguais mantém o valor True.

Métodos de Listas
A linguagem Python oferece alguns comandos, chamados métodos, capazes de
realizar determinadas operações sobre listas. Eles são acessados colocando um ponto
após o nome da variável e em seguida o nome do método terminado em abre e fecha
parênteses. Alguns métodos podem receber parâmetros os quais devem ficar no interior
dos parênteses. No código a seguir são apresentados alguns.

lista = [12, 3, 1, 6, 7]
[Link]() # Ordena os elementos de uma lista
[Link](4) # Adiciona o elemento 4 ao final da lista
[Link](12) # Remove o elemento com valor 12
[Link]() # Reverte a ordem da lista
[Link]() # Remove todos os elementos
[Link](0, 41) # insere o elemento 12 na posição 0 da lista
[Link]([6, 6, 6]) # adiciona os elementos da lista [6, 6, 6] ao final

Mais adiante neste tutorial “métodos” serão discutidos com mais detalhes.

Compreensão de Listas
Listas podem ser criadas também através das denominadas compreensão de listas,
semelhantes a notação de conjuntos encontrada na matemática.

[x for x in [1, 2, 3, 4, 5, 6] if x % 2 == 0]

Essa linha pode ser expressa matematicamente por:


19

A parte do if pode ser omitida e um range pode usado também:

[x**x | x in range(10, 20)]

Matematicamente:

Tuplas
Tuplas são semelhantes a listas, porém uma vez criadas não podem ser
modificadas. São declaradas como listas, porém, se utilizando de parênteses.

tupla = (1, 2, 3, 4, 5, 10)


print(tupla)

Tentar modificar um dos elementos gera um erro:

tupla = (1, 2, 3, 4, 5, 10)


tupla[5] = 6 # erro

Dicionários
Os dicionários são uma estrutura no qual os dados são armazenados da forma
chave-valor e podem ser acessados semelhantemente as listas e tuplas, porém
utilizando-se das chaves, ao invés dos índices. Além disso, diferentemente das tuplas, os
valores podem ser modificados ao decorrer da execução do programa. Outra questão
interessante e importante a respeito dos dicionários é que as chaves são únicas. Os
dicionários são declarados de forma literal a partir do uso de chaves e os respectivos
chave-valor são separados através do uso de chaves.
precosProdutos = {
"Laptop": 1999.99,
"Celular": 1599.99,
"Kit mouse + teclado": 99.99
20

}
print(precosProdutos["Laptop"])
for produto in precosProdutos:
print("Preco do {}: R${}".format(produto, precosProdutos[produto]))

Também é possível fazer a utilização de diversos métodos já implementados e


presentes neste tipo de estrutura de dados, como por exemplo os métodos get, len,
update, pop, keys, items, values e diversos outros que podem ser consultados através da
documentação oficial da linguagem.

Funções
Funções servem para evitar repetição de código além melhorar a organização e
clareza do programa. Uma função é declarada com a palavra-chave def seguido do nome
da função, abre e fecha parênteses, dois pontos e, na próxima linha indentada, o corpo da
função.

def saudacao():
print("Hello")

No código acima foi definido uma função chamada saudacao que ao ser executada
exibirá a mensagem "Hello". Note que, ao executar esse código nada acontece, pois a
função foi apenas declarada e não chamada.

Para chamar uma função deve-se escrever o nome dela seguido de abre e fecha
parênteses.

def hello():
print("Hello")
hello()

Agora sim, com o código acima, a mensagem será exibida.

Funções também podem receber parâmetros que permitem modificar o que a


função fará quando chamada. Por exemplo, podemos querer que a função hello diga
"Hello" seguido do nome de alguém.

def hello(nome):
print("Hello " + nome)
hello("Krzysztof Penderecki")

Pode-se passar quantos parâmetros quiser separando-os por vírgula.


21

def hello(nome, idade):


print("Hello " + nome + " você tem " + str(idade) + " anos")
hello("Krzysztof Penderecki", 87)

É possível que funções retornem valores. Para isso deve-se usar a palavra-chave
return seguido do valor a ser retornado.

def cubo(x):
return x*x*x
a = cubo(3)
print(a)

Nesse exemplo cubo retorna o cubo de um número e esse valor retornado foi
armazenado em uma variável.

def primo(n):
for i in range(2, n-1):
if n % i == 0:
return False
return True

A função acima verifica se um número é primo. Um número é primo somente se é


divisível por 1 e por ele mesmo. Essa função passa por todos os números entre 2 e o
próprio número menos 1, se algum desses números for divisor de n significa que n não é
primo. Agora, se passar por esses números e nenhum deles for divisor significa que n é
primo.

Exemplos
O exemplo a seguir calcula as raízes de uma equação do segundo grau a partir de
seus coeficientes.

def baskara(a, b, c):


delta = b**2 - 4*a*c
x1 = (-b + (delta**0.5)) / (2*a)
x2 = (-b - (delta**0.5)) / (2*a)
return (x1, x2)

Observe que essa função retorna uma tupla, isto deve ser levado em conta ao
utilizar os valores retornados:

t = baskara(-1, 7, 11)
print("x1 = " + str(t[0]))
print("x2 = " + str(t[1]))
22

Funções também podem ser recursivas, isto é, podem chamar a si mesmas. Uma
função recursiva muito conhecida é o fatorial que pode ser definido matematicamente por:

Em Python pode ser escrito da seguinte forma:

def fat(n):
if n <= 1:
return 1
else:
return n*fat(n-1)

Funções Lambda
Existe uma forma alternativa de declarar funções mais simples. Essa forma é
chamada de função lambda. Um exemplo é apresentado a seguir.

quad = lambda x : x*x

Esses tipos de funções não possuem nome e devem ser armazenadas em uma
variável. Os parâmetros vêm logo depois de lambda e separados por vírgula, e após os dois
pontos vem o corpo da função que deve ser uma expressão e é automaticamente
retornada. A função lambda do último exemplo retorna o quadrado de um número x. Já o
próximo exemplo retorna a média entre dois números.

media = lambda x, y: (x+y)/2

Essas funções são chamadas da mesma forma que as anteriores:

a = quad(4)
b = media(a, 5)
23

Programação Funcional

Módulos
Em Python, módulos são arquivos de código que podem ser trazidos para um
programa. Permitem que o programador possa utilizar em seu código funções, classes,
variáveis e etc. criados em outros arquivos.

Esses módulos podem ser trazidos para o programa através da linha de código
abaixo. A palavra reservada import seguido do nome do módulo.

import nome_do_modulo

Para criar um módulo para ser importado por um outro programa Python, basta
criar um arquivo de código fonte com a extensão “.py”. Por exemplo, a seguir está o
conteúdo do arquivo "[Link]":

# arquivo "[Link]"

def codificar(mensagem):
codificado = ""
for c in mensagem:
# "ord" transforma o caracter em um inteiro q é incrementado e
# convertido para caracter novamente com "chr"
codificado += chr(ord(c) + 1)
return codificado

def decodificar(mensagem):
decodificado = ""
for c in mensagem:
decodificado += chr(ord(c) - 1)
return decodificado

Agora é possível importar as funções deste módulo em um programa desde que


ambos os arquivos de código fonte estejam na mesma pasta.
24

# arquivo "[Link]"
import linguadoP

msg = "se para fazer iogurte precisa de um pouco de iogurte, de onde veio o
primeiro iogurte??"

msg_codificada = [Link](msg)

print(msg_codificada)

msg_decodificada = [Link](msg_codificada)

print(msg_decodificada)

Biblioteca Padrão
O Python quando instalado traz consigo diversos módulos que oferecem
funcionalidades básicas que provavelmente muitos programas necessitam, como funções
matemáticas, acesso a arquivos em disco, chamadas de funções do Sistema Operacional e
etc. Esses módulos são comumente chamados de biblioteca padrão da linguagem.

Um dos módulos mais utilizados da biblioteca padrão é o math que traz consigo
diversas funções matemáticas.

import math

# raiz quadrada de um numero


print([Link](16))
# seno de 30 graus (pi/6 em radianos)
print([Link]([Link]/6))
# cosseno de 60 (usando a função radians para converter para radianos)
print([Link]([Link](60)))
# logaritimo natural da constante e
print([Link](math.e))
# logaritimo na base 10 de 1000
print(math.log10(1000))

Outro módulo muito útil é o random que permite a geração de números aleatórios.
25

import random

def jogarDado():
return [Link](1, 6)

print(jogarDado())
print(jogarDado())
print(jogarDado())
print(jogarDado())

Os módulos também podem ser importados por partes através da palavra


reservada from.

from math import sqrt

def bhaskara(a, b, c):


delta = b**2 - 4*a*c
x1 = (-b + sqrt(delta))/2
x2 = (-b - sqrt(delta))/2
return (x1, x2)

print(bhaskara(1, -4, 4))

No código acima apenas a função sqrt de math foi importada e o uso do prefixo
"math" deixa de ser necessário ao usar a função.

Também é possível importar diretamente tudo do módulo usando o from e "*".

from math import *

def circuferenciaParametrizada(t, r, x0, y0):


return (r*cos(t) + x0, r*sin(t) + y0)

print(0.0, 1.0, 0.0, 0.0)


26

Orientação a Objetos
A Programação Orientada a Objetos (POO) é um paradigma de programação que
consiste na estruturação do código através do uso de dos chamados "objetos". Esses
objetos não são nada mais que um tipo de dado que carrega variáveis e funções dentro de
si. Um exemplo de objeto na linguagem Python é uma string.

a = "Taturana"
# Pode-se acessar por exemplo a função "upper" desse objeto string
b = [Link]()
print(b)

Também é possível criar seus próprios tipos de objetos através da palavra


reservada class. A seguir é definido o tipo de objeto "Barata" que representa uma barata e
possui algumas funções que simulam seu comportamento.

class Barata():
def voar(self):
print("bzzzzzzz")

def comer_lixo():
print("mnham mnham mnham hmmmmm")

A definição de um tipo de objeto é chamado classe e funções que pertencem a uma


determinada classe são chamadas de métodos.

Após definido o tipo do objeto pode-se de fato criá-lo e guardá-lo em uma variável.
Essa criação é chamada de instanciação. Para isso basta escrever o nome do objeto
seguido de abre e fecha parênteses, como se fosse a chamada de uma função. E para
chamar um determinado método desse objeto usa-se o nome da variável que recebeu o
objeto seguido do operador "." e a chamada da função.

# instanciação de um objeto
uma_barata = Barata()

# para chamar suas funções:


uma_barata.voar()
27

uma_barata.comer_lixo()

Construtores e Atributos
Também é possível que um objeto possua variáveis internas. Para criá-las é preciso
entender o conceito de construtor. O construtor é uma função que é chamada durante a
instanciação do objeto, ela sempre possui o nome de "__init__"(dois underlines no começo
e dois no final) e recebe um parâmetro chamado "self". A seguir um exemplo.

class Barata():
# definição do construtor
def __init__(self):
print("Uma baratinha nasceu!")

def voar(self):
print("bzzzzzzz")

def comer_lixo(self):
print("mnham mnham mnham hmmmmm")

# instanciação
uma_baratinha = Barata()

Durante a execução do programa acima será exibido na tela a mensagem "Uma


baratinha nasceu!" pois a criação de um objeto barata chamou o construtor do objeto.

Através do construtor podemos adicionar variáveis internas para o objeto. Para isso
usamos o parâmetro "self" que o construtor recebe.

class Barata():
def __init__(self):
[Link] = "Marcia"
[Link] = 23

Essas variáveis internas aos objetos são chamadas de atributos. Elas podem ser
acessadas de forma semelhante aos métodos, porém sem os parênteses:

barata = Barata()
# acessando atributo
print([Link])
28

# também é possivel modificar o atributo


[Link] = "Gertrudes"
print([Link])

O construtor também pode receber parâmetros, assim é possível customizar os


valores dos atributos de um objeto durante a sua instanciação.

class Barata():
def __init__(self, nome, idade):
[Link] = nome
[Link] = idade

E durante a instanciação passa-se os parâmetros como se fosse uma chamada a


uma função:

barata = Barata("João Baratista", 16)

print([Link])
print([Link])

Métodos também podem modificar os atributos de um objeto. Nesse caso, esses


métodos devem receber um parâmetro "self" que será usado para acessar o atributo
conforme o exemplo.

def Barata():
def __init__(self, nome, idade):
[Link] = nome
[Link] = idade

def fazer_aniversario(self):
print("Parabéns pra você, nesta data querida")
[Link] += 1 # "self" é usado para modificar um atributo do
objeto já criado no construtor

barata = Barata("Vanderlei", 51)


barata.fazer_aniversario()

print([Link])

Classes abertas
29

As classes da linguagem Python são chamadas de "abertas", pois podem ser


alteradas em qualquer lugar do código, mesmo após serem definidas, sendo possível
adicionar novos atributos e métodos. O mesmo se aplica a objetos.

class Barata():
def __init__(self, nome, idade):
[Link] = nome
[Link] = idade

# adicionando atributo a classe


[Link] = "Navegador"

barata_trabalhadora = Barata("Baratolomeu Dias", 15)

print(barata_trabalhadora.profissao)

# adicionando atributo ao objeto


barata_trabalhadora.destino = "O Cabo da Boa Esperança"

# criando função
def apresentacao(self):
print(f"Meu nome é {[Link]}, sou {[Link]} e vou cruzar
{[Link]}")

# adicionando a função acima como método da classe


[Link] = apresentacao

barata_trabalhadora.apresentacao()

A diferença entre adicionar um método (ou atributo) na classe e no objeto é que no


primeiro o método estará disponível para todos os objetos que são instâncias da classe, já
no segundo estará disponível apenas ao objeto ao qual foi adicionado.

As classes fechadas são aquelas que são implementadas pela própria linguagem
para representar tipos básicos, como strings, inteiros, listas e etc. Essas classes não
permitem a adição de novos atributos e métodos.

Atributos e Métodos Estáticos


Atributos estáticos são aqueles que são compartilhados entre todas as instâncias de uma
classe, ou seja, é como se o atributo fosse uma variável global, mas definida dentro da
classe. Além disso, esses atributos estáticos podem ser acessados e modificados sem
30

existir nenhuma instância da classe. Para defini-los basta fazer a declaração de uma
variável no escopo da classe, fora de qualquer método como no exemplo abaixo.

class Barata():
numero_de_baratas = 0

def __init__(self):
# devem ser acessadas dentro da classe
# indicando o nome da classe antes do ponto
Barata.numero_de_baratas += 1

# acessando atributo estático sem nenhuma instancia da classe


print(Barata.numero_de_baratas)

barata1 = Barata()
barata2 = Barata()
barata3 = Barata()
barata4 = Barata()
barata5 = Barata()

# acessando atributo estático de uma instância


print(barata3.numero_de_baratas)

Os métodos estáticos são semelhantes, podem ser acessados sem nenhuma


instância em qualquer lugar. Porém, eles não podem manipular atributos internos da
classe, somente atributos estáticos. Para criar um método estático é necessário usar o
decorador "@staticmethod" antes da declaração. Também não podem receber o
parâmetro "self". A seguir um exemplo:

class Barata():
numero_de_baratas = 0
idade_total = 0

def __init__(self, idade):


# devem ser acessadas dentro da classe
# indicando o nome da classe antes do ponto
Barata.numero_de_baratas += 1
Barata.idade_total += idade

@staticmethod
def idade_media():
return Barata.idade_total / Barata.numero_de_baratas
31

barata1 = Barata(15)
barata2 = Barata(121)
barata3 = Barata(3)
barata4 = Barata(49)
barata5 = Barata(69)

# acessando atributo estático de uma instância


print("A idade média das baratas é", Barata.idade_media())

Propriedades
Propriedades são atributos cujo acesso e modificação são controlados por métodos.
É muito útil para validar a modificação de um atributo. Por exemplo, se um determinado
atributo representa um dia do mês, não é desejável que alguém possa modificá-lo de
modo a inserir um número maior do que 31 ou menor que 1. Também seria necessário
verificar se o mês tem 30 ou 31 ou dias.

Existem duas formas de se definir uma propriedade, através do decorador "@property" ou


da função "property". A seguir um exemplo com a primeira. Um decorador é simplesmente
uma palavra chave começada com "@" colocado antes da definição de alguma variável,
função, classe e etc.

class Aniversario():
def __init__(self):
[Link] = 1975
[Link] = 1
self._dia = 1

# função que verifica se ano é bissexto


def ehBissexto(self, ano):
if ano % 4 == 0 and not (ano % 100):
return True
elif ano % 4 == 0 and ano % 100 == 0 and ano % 400:
return True
else:
return True

# define o método property


# esse método será responsável por obter o valor do atributo
@property
def dia(self):
32

return self._dia

# define o método que corresponderá ao setter da propriedade,


# isto é, o método que modificará o atributo.
# A sintaxe desse decorador é: "nome da propriedade", "." e "setter"
@[Link]
def dia(self, dia):
diaMaximo = 31
# calcula o dia máximo com base no ano e mes
if [Link] == 2: # se for fevereiro
if [Link]([Link]):
diaMaximo = 29
else:
diaMaximo = 28
elif [Link] in [4, 6, 9, 11]: # se for um mes com 30 dias
diaMaximo = 30

# verifica se o dia está entre 1 e diaMaximo


if dia > diaMaximo:
self._dia = diaMaximo
elif dia < 1:
self._dia = 1
else:
self._dia = dia

aniversario = Aniversario()

[Link] = 2020
[Link] = 2
# usa-se a propriedade "dia" normalmente como se fosse um atributo
[Link] = 34

print([Link])

Repare que é necessário que as funções de "get" e "set" tenham o mesmo nome. E
este nome deve ser diferente do atributo que essas funções estão relacionadas, por isso o
atributo "dia" foi chamado “_dia" neste exemplo.

A segunda forma de se definir propriedades é utilizando a função "property":

class Aniversario():
def __init__(self):
33

[Link] = 1975
[Link] = 1
self._dia = 1

# função que verifica se ano é bissexto


def ehBissexto(self, ano):
if ano % 4 == 0 and not (ano % 100):
return True
elif ano % 4 == 0 and ano % 100 == 0 and ano % 400:
return True
else:
return True

# esse método será responsável por obter o valor do atributo


def get_dia(self):
return self._dia

# esse método corresponderá ao setter da propriedade,


def set_dia(self, dia):
diaMaximo = 31
# calcula o dia máximo com base no ano e mes
if [Link] == 2: # se for fevereiro
if [Link]([Link]):
diaMaximo = 29
else:
diaMaximo = 28
elif [Link] in [4, 6, 9, 11]: # se for um mes com 30 dias
diaMaximo = 30

# verifica se o dia está entre 1 e diaMaximo


if dia > diaMaximo:
self._dia = diaMaximo
elif dia < 1:
self._dia = 1
else:
self._dia = dia

# atributo estático
dia = property(get_dia, set_dia)

aniversario = Aniversario()
34

[Link] = 2020
[Link] = 2
# usa-se a propriedade "dia" normalmente como se fosse um atributo
[Link] = 34

print([Link])

Nesse formato é criado um atributo estático com o nome da propriedade que


recebe a função "property" passando como argumentos os métodos "get" e "set".

Herança
Outro pilar básico da programação orientada a objetos é o conceito de herança.
Herança consiste em uma classe herdar métodos e atributos de uma classe base. Isso é
muito útil pois evita que classes muito parecidas sejam escritas totalmente do zero.
Também é ideal para modelar a relação entre objetos do mundo real, permitindo que um
conjunto de objetos possam ser agrupados de acordo com suas características em comum.

Para herdar de uma classe basta colocar o nome da classe mãe entre parênteses na
declaração da classe conforme o exemplo a seguir:

# classe base
class Barata():
def __init__(self, nome, idade):
[Link] = nome
[Link] = idade
def comer_lixo(self):
print("hmmmm mnham mnham mnham")

# classe que herda da base


class BarataVereadora(Barata):
def __init__(self, nome, idade, numero, ano_posse):
[Link] = numero
self.ano_posse = ano_posse
# necessario chamar manualmente o construtor da classe base
Barata.__init__(self, nome, idade)

def discursar(self):
print(f"Ola povo! Meu nome é {[Link]} e eu prometo não roubar.
Vote {[Link]}!")
35

vereador = BarataVereadora("Barata Obama", 51, 666, 2049)

vereador.comer_lixo()
[Link]()

Observe que mesmo sem definir os atributos "nome", "idade" e o método


"comer_lixo" na classe "BarataVereadora", eles puderam ser utilizados normalmente na
classe devido a herança de "Barata".

Também é importante ressaltar a necessidade de se chamar o construtor da classe


base no construtor da classe derivada. É a chamada deste construtor que irá criar a
definição dos atributos da classe.

A linguagem Python também tem suporte a herança múltipla em que uma classe
pode herdar de mais de uma classe base. Para isso deve-se colocar as classes separadas
por vírgula durante a definição da classe:

class Aranha():
def __init__(self):
pass
def soltar_teia(self):
print("*barulho de lançar teia*")
def sentido_aranha(self):
print("*barulho do sentido aranha*")

class BarataAranha(Barata, Aranha):


def __init__(self, nome, idade):
Barata.__init__(self, nome, idade)
Aranha.__init__(self)

barata_aranha = BarataAranha("Peter Barater", 18)


barata_aranha.comer_lixo()
barata_aranha.soltar_teia()

Sobrecarga de Operadores
36

Em Python é possível definir como operadores como +, -, *, % se comportaram com


uma classe definida pelo usuário. Para isso basta definir, segundo a tabela a seguir, o
método do respectivo operador na classe.

Operador Método Operação Padrão

__add__
+ adição

- __sub__ subtração

* __mul__ multiplicação

/ __div__ divisão

// __floordiv__ divisão inteira

% __mod__ módulo

__pow__
** potência

__pos__
+ positivo

- __neg__ negativo

< __lt__ menor que

> __gt__ maior que

<= __le__ menor ou igual a

>= __ge__ maior ou igual a

\== __eq__ Igual a


37

!= __ne__ diferente de

<< __lshift__ deslocamento para


esquerda

>> __rshift__ deslocamento para direita

& __and__ e bit-a-bit

| __or__ ou bit-a-bit

^ __xor__ ou exclusivo bit-a-bit

~ __inv__ inversão

A seguir um exemplo da sobrecarga do operador “+” através do método "__repr__".


Também que é definido o método "__repr__" que é usado pelo comando "print" para
converter o objeto para string e printá-lo.

class Vector3():
def __init__(self, x = 0, y = 0, z = 0):
self.x = x
self.y = y
self.z = z

# definindo o comportamento do operador + (soma)


def __add__(self, vec):
return Vector3(self.x + vec.x , self.y + vec.y, self.z + vec.z)

# definindo o comportamento do operador - (subtração)


def __sub__(self, vec):
return Vector3(self.x - vec.x , self.y - vec.y, self.z - vec.z)

# esse método é usado pelo comando "print" para converter o objeto para
string e printa-lo
def __repr__(self):
38

return "%f, %f, %f" % (self.x, self.y, self.z)

vec1 = Vector3(1.0, 1.0, 1.0)


vec2 = Vector3(1.0, -1.0, 1.0)
vec3 = Vector3(0.4, -3.0, -1.3)

vec4 = vec1 + vec2 - vec3;

print(vec3)

Exemplo Final 1 - Jogo da Forca


Nesta seção será apresentado um exemplo para reforçar boa parte do que foi
abordado neste tutorial. O exemplo consiste em um simples jogo da forca que rodará
diretamente do terminal. O código é apresentado a seguir e os principais pontos são
esclarecidos através de comentários.

# Essa função é responsável por desenhar a forca em si.


# Dependendo do número de erros, "e", partes do corpo
# São desenhadas na forca
def desenha_forca(e):
print(" __ ")
print("| | ")
if e == 0:
print("|")
print("| ")
print("| ")
print("|")
elif e == 1:
print("| O ")
print("| ")
print("| ")
print("| ")
elif e == 2:
print("| O ")
print("| |")
print("|")
print("| ")
elif e == 3:
print("| O ")
print("| /|\\")
39

print("| ")
print("| ")
elif e == 4:
print("| | ")
print("| O ")
print("| /|\\")
print("| / \\")
print("| ")
elif e == 5:
print("| O ")
print("| ")
print("| /|\\")
print("| / \\")
print("-------------")

# Essa função verifica


# Se um elemento é membro de uma lista
def eh_elemento(e, lista):
for l in lista:
if e == l:
return True
return False

# Printa as lacunas da palavra a ser advinhada,


# exibindo apenas as lestras que foram faladas
def printa_palavra(letras, palavra):
saida = []
for l in palavra:
if eh_elemento(l, letras):
[Link](l)
else:
[Link]("_")
for e in saida:
# O "end=1''" serve para que o print exiba uma mensagem
# sem pular linha
print(e," ", end='') # O "end=''" serve para que o print

# Verifica se todas as lestras da palavra ja foram faldas


def completou(letras, palavra):
for l in palavra:
if not eh_elemento(l, letras):
return False
40

return True

# É onde acontece o jogo


def jogo():
fim_de_jogo = False # Indica se o jogo acabou ou não
erros = 0 # Quantidade de letras faladas
palavra_secreta = "couve" # Palavra que será adivinhada
letras_inseridas = [] # Letras que foram faladas

while fim_de_jogo == False:


desenha_forca(erros)
printa_palavra(letras_inseridas, palavra_secreta)
# Lê letra do usuário
letra_usuario = input("Entre com uma letra: ")

# Verifica se a letra ja foi falada antes


if eh_elemento(letra_usuario, letras_inseridas):
erros += 1
print("Essa letra ja foi")
# Verifica se a letra nao faz parte da palavra
elif not eh_elemento(letra_usuario, palavra_secreta):
erros += 1
print("Essa letra não faz parte da palavra")

# Insere letra na lista de letras faladas


letras_inseridas.append(letra_usuario)

# Verifica se o jogador ganhou o jogo


if completou(letras_inseridas, palavra_secreta):
fim_de_jogo = True
print()
printa_palavra(letras_inseridas, palavra_secreta)
print()
print("PARABÉNS VOCÊ GANHOU")
# Verifica se o jogador perdeu
elif erros >= 5:
desenha_forca(erros)
fim_de_jogo = True
print("VOCÊ PERDEU")

jogo() # Inicia o jogo


41

Exemplo Final 2 - Aprendendo um pouco sobre uma biblioteca gráfica


Neste exemplo será introduzido uma biblioteca gráfica, para que você possa
conseguir fazer um programa já com interação a eventos. Assim, será utilizada a biblioteca
Tkinter, que já faz parte das bibliotecas padrão do python e que portanto, não será
necessário realizar sua instalação. Será construído através deste exemplo um programa
com formulário e uma espécie de “banco de dados” em memória.
Primeiramente, é necessário importar a respectiva biblioteca.
import tkinter as tk

Feito isso, pode-se declarar a classe principal da nossa aplicação, que será derivada
do componente Frame da biblioteca Tkinter, e que portanto, também será uma Frame. As
respectivas funções de cada linha do código serão comentadas, para que exista
entendimento a partir de sua leitura.

class Application([Link]):
def __init__(self, master=None):
super().__init__(master) #constroi a janela base, o root.

# atribui o root para uma var local, a fim de poder usar algumas
de suas propriedades
[Link]

# define tamanho da janela root


[Link]("600x500")

# define título da janela root


[Link]("Produtos")

# var local, para simular um "banco de dados", com o uso de


dicionários
[Link] = {}

# criação de um Frame, a fim de organizar e manter os


produtos em tela
[Link] = [Link](self)
42

# organiza os widgets em blocos e os insere nos frames


[Link]()

# método local, responsável por criar o restante dos widgets


da aplicação
self.create_widgets()

O método create_widgets, interno da classe Application, foi implementado da


seguinte maneira.

def create_widgets(self):

# cria o Label representado o logo da aplicação


[Link](self, text="Produtos", font = ("Arial", 15,
"bold")).pack(side="top", ipadx=10, ipady=10)

# cria o formulário para inserção de novos produtos


[Link]()

# responsável pela visualização, em forma de lista, dos


produtos
[Link]()

Os métodos productForm e productList, foram implementados das seguintes formas.

Método productForm()

def productForm(self):

# criação do frame base para o formulário


[Link] = [Link](self)

# criação e inserção no container do label do input Nome


[Link]([Link], text="Nome: ", font =
10).grid(row = 0, column = 0)
43

# criação do campo input Nome


[Link] = [Link]([Link], font=10)

# inserção no container do campo input Nome


[Link](row = 0, column = 1)

# criação e inserção no container do label do input Preço


[Link]([Link], text="Preço: ", font =
10).grid(row = 1, column = 0)

# criação do campo input Preço


[Link] = [Link]([Link], font=10)

# inserção no container do campo input Preço


[Link](row = 1, column = 1)

# insere o container na janela principal


[Link]()

# criação do botão para salvar novo produto


[Link] = [Link](self, text="Salvar",
command=[Link])

# insere na janela principal o botão


[Link](side="top", pady=10)

Método productList()
def productList(self):

# limpa o conteúdo container de produtos


for widget in [Link].winfo_children():
[Link]()

# cria e insere os Labels Produto e Preço, no container de


produtos
[Link]([Link], text="Produto",
font=("Arial", 9, "bold")).grid(row = 0, column = 0)
44

[Link]([Link], text="Preço R$",


font=("Arial", 9, "bold")).grid(row = 0, column = 1)

# itera sobre os produtos disponíveis em memória e, cria seus


respectivos labels, para que eles sejam listados na tela
line = 1
for name, price in [Link]():
[Link]([Link],
text='{name}'.format(name=name,price=price)).grid(row = line, column
= 0)
[Link]([Link],
text='R${price}'.format(price=price)).grid(row = line, column = 1)
line += 1

# insere o container de produtos na janela principal


[Link]()

Como pode ser observado na linha de código responsável por criar o botão Salvar,
no método productForm(), foi realizado um bind, ou seja, uma vinculação de evento ao
clicar no botão. Essa vinculação ocorreu a partir do argumento passado para o parâmetro
command. Desse modo, como foi passado uma função, denominada [Link], é necessário
que tenhamos também ela implementada em nosso código.

Método save()
def save (self):

# cria ou atualiza a chave "[Link]()" com o valor


"[Link]()"
[Link][[Link]()] = [Link]()

# gera a lista de produtos atualizada


[Link]()

Por fim, é necessário que nossa classe Application seja instanciada, para que
possamos criar nosso objeto e desse modo, a aplicação possa ficar rodando e esperando a
interação com o usuário.
45

# janela root do Tkinter


root = [Link]()

# instancia um objeto app, passando como argumento a janela root


app = Application(master=root)

# chama o método de loop


[Link]()

Computação Científica com Python

Como o Python é uma das linguagens mais utilizadas no mundo, não é nenhuma surpresa
que ele possua uma extensa coleção de bibliotecas para computação científica disponível
na internet. A biblioteca mais famosa nesse campo é sem dúvidas a Numpy, ela fornece
uma ampla quantidade de funções e estruturas de dados capaz de tornar o Python um
concorrente de Softwares na área, tais como Matlab, Scilab e Octave. Uma outra biblioteca
muito importante que trabalha juntamente com a Numpy é o Matplotlib, que auxilia na
plotagem de gráficos, e também a Pandas, que é usada para análise e representação de
dados.

Numpy
Numpy, abreviação de Numerical Python, é a principal biblioteca de computação numérica
da linguagem, sendo utilizada como base para diversas outras bibliotecas que precisam
executar esse tipo de atividade. É extremamente rápida com operações sobre listas, pois
utiliza um tipo próprio de lista chamado ndarray que por baixo dos panos é semelhante
aos arrays da linguagem C. Além dos ndarrays, essa biblioteca fornece ainda diversas
funções matemáticas relacionadas à álgebra linear, geração de números aleatórios,
transformadas de Fourier e etc.
46

Instalação
Para instalar o numpy é bem simples, basta abrir um terminal e executar o seguinte
comando:
pip install numpy

O comando pip é o gerenciador de pacotes do Python, ele permite instalar, atualizar e


remover módulos da linguagem. Para instalar um módulo deve-se passar o argumento
install seguido do nome do módulo.
Para usar a biblioteca em seu código é necessário importar seu módulo que possui o nome
numpy.
import numpy

Para evitar de se escrever numpy antes de toda a chamada de função poderia-se importar
tudo que existe dentro do módulo da seguinte forma:
from numpy import *

Porém isso traria para o escopo global funções do Numpy que entrariam em conflito com
outras funções do Python, como a função max. Por isso é recomendado importar o módulo
e renomeá-lo para um nome mais curto como “np”.
import numpy as np

Assim as funções do Numpy podem ser chamadas da seguinte forma:


[Link]([1,2,3,4])

Arrays
Como dito anteriormente o Numpy implementa o seu próprio tipo de lista chamado
ndarray que é semelhante aos arrays da linguagem C e tão rápido quanto. Para se declarar
um ndarray em Python a partir de uma lista usa-se a função array.
[Link]([2,6,2,8,4,3])

Diferentemente das listas em Python um ndarray não pode conter elementos de tipos
diferentes, ou seja, não se pode criar um array com um elemento do tipo inteiro, outro
elemento do tipo booleano e outro com o tipo string por exemplo.
A maioria das operações realizadas com as listas em Python também são suportadas pelos
ndarrays.
a = [Link]([2, 6, 2, 8, 4, 3])
# acessar elemento
47

print(a[3])
# modificar elemento
a[3] = 12
print(a[3])
# número de elementos
print(len(a))
# percorrer com um for
for elem in a:
print(elem)

Outra forma de se criar ndarrays é através da função arange que é semelhante a função
range do Python. Por exemplo, para se criar um ndarray com os números pares entre 0 e
100:
[Link](0, 100, 2)

Outra grande vantagem dos ndarrays sobre as listas do Python é que operações básicas
realizadas entre valores escalares também podem ser realizadas nos ndarrays usando a
mesma sintaxe. Por exemplo, pode-se multiplicar todos os elementos do array da seguinte
forma.
a = [Link]([2, 6, 2, 8, 4, 3])
b = a * 10
# b é um ndarray com os valores [20, 60, 20, 80, 40, 30]

Como era de se esperar isso se aplica para outras operações básicas:


a = [Link]([2, 6, 2, 8, 4, 3])
b = a + 10 # 10 é somado a cada elemento do array
c = a / 4 # cada elemento é dividido por 4
d = a ** 2 # cada elemento é elevado ao 4

A variável b no código acima será um ndarray com os valores de a multiplicados por 10.
As operações também podem ser realizadas entre ndarrays.
a = [Link]([2, 3, 6])
b = [Link]([3, 2, -1])

c = a + b # os elementos de c são as somas par a par dos elementos de "a"


# e "b", [5, 5, 5]
d = a - b # a mesma coisa, só que para subtração, [-1, 1, 7]
e = a * b # a mesma coisa, só que para multiplicação, [6, 6, -6]
48

# (observe que no caso acima não é realizado produto interno)

Importante ressaltar que as operações devem ser realizadas entre ndarrays com o mesmo
número de elementos.

Matrizes
Matrizes são arrays bidimensionais, ou seja, um determinado elemento deve ser acessado
utilizando dois índices, um que indica a coluna e outro a linha. Para representar esse tipo
de estrutura com Numpy criamos ndarrays de ndarrays. Uma das formas de se realizar isso
é passar para a função [Link] uma lista de listas, o exemplo a seguir deixará mais claro:
matriz = [Link]([ [10, 12], [23, 14] ])

O código criará uma representação da matriz abaixo.

Onde cada matriz interna representa uma linha. Note que é necessário que todas as linhas
tenham o mesmo número de elementos.
Para acessar um elemento dessas matrizes é trivial:
#acessar elemento 12
print( matriz[0][1] )
# acessar elemento 23
print( matriz[1][0] )

Onde o primeiro valor entre colchetes é o índice da linha e o segundo é o índice da coluna.

Um atributo importante presente nos ndarrays é o shape que consiste em uma tupla de
valores inteiros que indicam o formato da matriz. No caso da matriz dos exemplos
anteriores, ao acessar esse atributo, temos a tupla (2, 2) que indica que essa matriz possui
duas linhas e duas colunas.

matrix2 = [Link]([ [1, 2, 3, 4], [25, 26, 27, 28] ])


print([Link])

Para o código acima será exibido a tupla (2, 4) indicando que a matriz possui 2 linhas e 4
colunas.

Outra maneira de criar matrizes é utilizando as funções [Link] e [Link]. A primeira cria
uma matriz preenchida com 0s e a segunda uma matriz preenchida com 1s. Ambas
49

funções recebem um valor escalar ou tupla como argumento. Passando um escalar n,


essas funções retornam um array unidimensional com n elementos. Já com uma tupla
contendo 2 elementos, essas funções retornam uma matriz com o formato indicado por
essa tupla.
a = [Link](10) # cria uma array com 10 elementos, todos com valor 0.
a = [Link]((3, 5)) # cria uma matriz com 3 linhas e 5 colunas onde todos
# os elementos são 1s.

Também existem outras funções para se criar arrays, como por exemplo, [Link] que cria
uma matriz identidade com o formato especificado pela tupla que recebe, e também [Link]
que é semelhante a zeros e ones com a diferença que recebe de argumento, além de uma
tupla, o valor que será usado para preencher.
Na realidade é possível criar ndarrays com um número arbitrário de dimensões. Para se
criar um array tridimensional por exemplo deve-se passar uma lista de lista de lista para a
função [Link], ou usar as funções [Link], [Link] e etc. passando uma tupla com 3
elementos.

Indexação de Arrays
Os ndarray oferecem alguns recursos avançados de indexação de arrays. Um deles é o
chamado slicing que permite obter sub-arrays de um array da seguinte forma:
a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
b = a[0:3] # "b" possui os elementos ['a', 'b', 'c'],
# o elemento de índice 3 não é incluído

Usando a sintaxe acima é possível extrair um subarray de um determinado array. Entre os


colchetes ao invés de ser passado um único valor é passado um intervalo indicando o
índice dos elementos que formarão o sub array. O valor a esquerda do “:” indica em qual
elemento começará o subarray e o segundo o índice do elemento que deixaŕa de fazer
parte do sub-array, logo esse elemento não será incluído.

Também é impossível omitir o valor da lado esquerdo ou direito do “:”, indicando


respectivamente para se começar o primeiro elemento, ou terminar no último.
Omitindo-se ambos valores é retornado o array inteiro.
a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
b = a[:3] # "b" possui os elementos ['a', 'b', 'c'],
c = a[4:] # "c" possui os elementos ['e', 'f']
d = a[:] # "d" possui os elementos ['a', 'b', 'c', 'd', 'e', 'f']
50

Uma diferença crucial entre as listas do Python e os ndarrays é que o segundo não faz uma
cópia dos elementos ao gerar o sub-array. Isso significa que ao se modificar um subarray
essa mudança acaba sendo refletida no array original.
a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
b = a[0:3]
b[0] = 'x'
b[1] = 'x'
b[2] = 'x'
print(a) # será printado: array (['x', 'x', 'x', 'd', 'e', 'f'])

Como o Numpy foi pensado para ser extremamente eficiente com arrays, ele dificilmente
cria cópias do mesmo, pois é uma operação computacionalmente muito custosa. Caso
realmente seja necessário copiar um subarray pode-se usar o método copy.
a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
b = a[0:3].copy() # "b" armazenará uma cópia do sub-array, modificar ele
# não irá alterar os elementos de "a"

Graças a essa característica é possível atribuir a vários elementos de um array um mesmo


valor, isso é chamado pelo Numpy de broadcast.
a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
a[0:3] = 'x'
print(a) # será printado: array (['x', 'x', 'x', 'd', 'e', 'f'])

Também pode-se usar “[:]” para atribuir um valor a todos os elementos.


a = [Link](['a', 'b', 'c', 'd', 'e', 'f'])
a[:] = 'x'
print(a) # será printado: array (['x', 'x', 'x', 'x', 'x', 'x'])

Os mesmos princípios são válidos para arrays com mais de uma dimensão. Uma dica é que
para estes tipos de arrays pode-se acessar um elemento passando os índices separados
por vírgula dentro do mesmo par de colchetes:
a = [Link]([ [1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12] ])
b = a[1, 2] # acessar o elemento da linha 1 e coluna 2, elemento 7 no caso
c = a[0:2, 2:] # acessando o subarray [[3, 4], [7, 8]]
d = a[:, 3:] # acessando o sub array [[4], [8], [12]]
51

Outro recurso interessante é a capacidade de se selecionar elementos de um ndarray


baseado em determinada condição booleana. Os operadores relacionais como “>”, “<”, “==”,
“!=” e etc. são sobrecarregados para operarem em ndarrays. Logo o seguinte é possível:
a = [1, 2, 3, 4, 5]
print( a >= 3) # será printado: [False, False, True, True, True]

Será gerado um novo ndarray onde cada elemento indica se a condição foi satisfeita para o
respectivo elemento do primeiro ndarray. Esse novo array gerado pode ser usado para
indexar um ndarray de mesmo tamanho.
a = [1, 2, 3, 4, 5]
b = a >= 3 # b = [False, False, True, True, True]
c = a[b] # c = [3, 4, 5]

Ou de maneira mais direta:


a = [1, 2, 3, 4, 5]
c = a[a >= 3] # c = [3, 4, 5]

Funções matemáticas do Numpy


O Numpy re-implementa diversas funções matemáticas da biblioteca padrão math. Isso é
feito porque as funções do math não suportam broadcast, ou seja, não conseguem operar
diretamente sobre arrays. Caso quisesse aplicar a função sin em todos os elementos de
uma lista, seria necessário utilizar um for ou a função map. Porém com a função sin
implementada pelo numpy pode-se passar diretamente o array como argumento.
dados = [0.1, 0.3, 0.5, 0.7, 0.9, 1.1]
[Link](dados) # retorna uma lista com os senos dos números em dados

Também é disponibilizado pelo Numpy um submódulo que oferece diversas funções


relacionadas à álgebra linear. O nome do módulo é linalg.
import [Link] as la

Algumas das funções oferecidas:


import numpy as np
import [Link] as la

mat1 = [Link]([[3, 2],


[4, 1]])
mat2 = [Link]([[9, 3],
[4, 8]])
52

# determinante de uma matriz


print([Link](a))
# calcula inversa de uma matriz
print([Link](a))
# multiplicação de matrizes
print(mat1 @ mat2)
# resolução de sistema linear de equações
# 3x + 2y + 4z = 1
# x + y + 2z = 2
# 4x + 3y - 2z = 3

A = [Link]([[3, 2, 4],
[1, 1, 2],
[4, 3, -2]])

b = [Link]([1, 2, 3])

print([Link](A, b))

Jupyter Lab
Uma ferramenta muito popular entre os programadores que trabalham com computação
numérica e análise de dados é o Jupyter Lab. Esta ferramenta open source oferece um
ambiente de desenvolvimento onde código e dados possam ser trabalhados de forma
interativa. Instruções para se utilizar cada uma dessas ferramentas pode ser encontrada
no site oficial.
Para esse tutorial será utilizado uma versão mais simples do Jupyter Lab chamado Jupyter
Notebook, que embora com menos funcionalidades será suficiente para este tutorial. Para
acessá-lo, a partir do site oficial, clique no botão “Try it in your browser”.
53

Na próxima página selecione usar o Notebook Clássico.

Agora aguarde alguns segundos enquanto o notebook é carregado. Assim que terminar e a
tela de “bem vindo” for exibida vá até o menu File, New Notebook e Python 3.
54

Se tudo ocorrer como o esperado você se deparará com a seguinte tela.

No campo de texto indicado pela seta vermelha pode-se escrever código Python.
Experimente escrever um simples hello world. Para executar o código basta clicar no botão
Run indicado pela seta verde, ou pressionar a tecla ctrl e enter ao mesmo tempo. A saída
do código será exibida em uma nova linha abaixo.
Cada um desses pares de código e saída é chamada célula. O que torna o Jupyter muito
prático é a possibilidade de se criar várias dessas células cada uma sendo executada de
maneira cooperativa. Para criar uma nova célula pode-se utilizar o botão indicado pela seta
azul.
Suponha que por exemplo tenha-se a seguinte célula:

Ao executá-la, as variáveis declaradas serão válidas para todas as células seguintes. Dessa
forma pode-se criar uma nova célula que utiliza essas variáveis.
55

Isso é muito útil para situações em que um determinado trecho de código leva muito
tempo para ser executado. Em vez de se executar todo o código após realizar uma
pequena modificação pode-se colocar o trecho de código mais demora em uma célula
separada e executar somente aquela que precisa de modificações.
Outro ponto importante dessas células é que caso a última linha de código seja uma
expressão, isto é, algo que retorna algum valor, esse valor será exibido na saída da célula.

Uma outra funcionalidade muito importante do Jupyter é a capacidade de exibir gráficos,


tabelas e imagens. Para isso é necessário utilizar a biblioteca Matplotlib.

Matplotlib

É uma biblioteca que oferece diversas funcionalidades para plotar gráficos e imagens. Se
integra muito bem com o Numpy. A instalação pode ser realizada através do pip rodando o
seguinte comando em um terminal:

pip install numpy

Todas as funcionalidades que serão utilizadas nesse tutorial estão contidas no submódulo
pyplot, por isso somente ele será importado. Além disso, é uma convenção renomeá-lo
para plt.

import [Link] as plt


56

Para plotar um grafo é bem simples, basta usar a função plot.

Como foi dito anteriormente, se a última linha da célula for uma expressão o valor dela é
exibido. No caso acima [Link](data) retorna um objeto [Link].Line2D que é lido
pelo Jupyter Notebook e exibido como uma imagem.

A função plot possui uma infinidade de parâmetros que podem ser passados. Quando
apenas uma lista (ou ndarray) é passado para essa função é criado um gráfico de duas
dimensões onde o eixo “y” é representado pelos valores da lista e o eixo “x” pelos índices
dessa lista.

Também é possível passar duas listas ou arrays como argumento da função plot, a primeira
corresponderá ao eixo “x” e a segunda ao eixo “y”, note que ambas devem ter o mesmo
57

tamanho. No exemplo a seguir é criado uma onda senoidal com frequência de 10 Hz com
duração de 0,5 segundos.

O eixo “x” que representa os segundos é criado com a função arange do Numpy
consistindo em um array cujo os elementos representam os instantes de 0 a 0,5 segundos
espaçados por 0,001 segundos. Já o eixo “y” é calculado a partir do “x” aplicando-o uma
função. Nesse caso é aplicado a função senoidal, repare que não é utilizado a função sin da
biblioteca padrão do Python, mas sim a do Numpy por causa do broadcasting. Para se
conseguir a onda senoidal com a frequência desejada de 10 Hz, cada valor de x é
multiplicado por 2 × π × 𝑓𝑟𝑒𝑞𝑢ê𝑛𝑐𝑖𝑎. Para plotar o gráfico passa-se o array “x” como o
primeiro argumento de plot e “y” como o segundo.

A função plot possui diversos parâmetros para customizar a aparência da plotagem. A


maioria dessas customizações são feitas passando uma string como último argumento. Por
exemplo, para que a curva do gráfico tenha a cor vermelha pode-se usar um ‘r’ (red) na
string:
58

Outros caracteres podem ser indicados para representar o restante das cores disponíveis
como indicado na tabela a seguir.

Caractere Cor

‘b’ azul (blue)

‘g’ verde (green)

‘r’ vermelho (red)

‘c’ ciano (cyan)

‘m’ magenta
59

‘y’ amarelo (yellow)

‘k’ preto (black)

‘w’ branco (white)

Também é possível determinar o estilo das linhas do gráfico, podendo ser tracejado '--',
pontilhado ':', sólido '-' ou ponto e traço '-.'. Os pontos do gráfico também podem
receber alguma marcação especial, por exemplo usando o caractere 'o', resultará em
marcações circulares e o caractere 'v' em marcações de formato triangular para baixo.
Observe a seguir que essas formações podem ser combinadas.

Com o Matplotlib também é possível colocar um título no gráfico e nomear os eixos, para
isso usa-se as funções abaixo:
60

Também podem ser criados outros tipos de gráficos além dos criados com a função plot.
Por exemplo, pode-se criar um gráfico de barras utilizando a função bar. É semelhante a
função plot com a diferença que o eixo x pode conter valores não numéricos como strings.
No exemplo a seguir é criado um gráfico de barras que representa as chuvas durante o
ano de 1634.
61

Também pode-se criar um gráfico de pizza com a função pie. Basta passar uma array ou
lista que o matplotlib irá automaticamente criar uma gŕafico de pizza baseado na
proporção de cada número em relação ao total. Também é possível passar um parâmetro
opcional do tipo array chamado label especificando um label para cada valor.
62

Em algumas ocasiões pode ser oportuno exibir vários gráficos em uma mesma figura.
Múltiplos gráficos podem ser criados com a função subplots. Os gráficos criados por ela
são dispostos em forma de matriz, ou seja, a figura é dividida em vários retângulos, cada
um contendo um gráfico. Essa função recebe dois parâmetros indicando o número de
linhas e colunas respectivamente da matriz. Por exemplo, para se criar uma figura
contendo quatro gráficos, dois na linha de cima e dois na linha:
[Link](2, 2)
63

Essa chamada de função retorna uma tupla com dois elementos, o primeiro é um objeto
que representa a figura como um todo. O segundo é uma matriz onde cada elemento é do
tipo axis, um objeto que representa um gráfico e que pode ser plotado com o método plot.
A seguir são criados 4 gráficos, cada um contendo um gráfico de um tipo diferente.

SMTP Simple Mail Transfer Protocol

SMTP é a sigla para Simple Mail Transfer Protocol que significa protocolo de transferência
de correio simples. Em sumo é um padrão para o envio de correspondência digital,
funciona basicamente da seguinte forma para enviar um email de uma conta para outra.

smtplib
Para instalar a smtplib usando o pip no terminal:
pip install smtplib

Para usar a biblioteca deve-se importar o smtplib:


64

import smtplib

Para realizar o envio de email é necessário saber qual o endereço smtp para o seu
provedor de email, alguns dos provedores mais comuns são:
● Gmail: [Link]
● Hotmail: [Link]
● Outlook: [Link]
● Yahoo: [Link]

para realizar o envio do email:


my_email = "**********@[Link]"
password = "********"
with [Link]("[Link]") as connection:
[Link]()
[Link](user = my_email, password = password)
[Link](
from_addr = my_email,
to_addrs = "**********@[Link]",
msg = f"Subject:Mensagem\n\n{msg_de_hoje}"
)

Os asteriscos foram usados para representar os dados pessoais, com my_email e password
sendo o email de quem está enviando, o email de envio é um gmail, então é usado
“[Link]” , [Link]("[Link]") cria um objeto da classe SMTP que vai ser
chamado de connection, dentro desse escopo determinado por tudo que está dentro do
with. Em seguida é usado o stattls(), TLS significa Transport Layer Security e é uma forma de
assegurar a conexão ao servidor de email, em seguida é feito o login() e o email é enviado
usando sendmail(). Por estar enviando um email a partir de uma ferramenta externa, é
necessário desabilitar as ferramentas de segurança do email usado para o envio, portanto
é recomendado criar um email apenas para uso na aplicação.

Requests

Trata-se de uma biblioteca HTTP Hypertext Transfer Protocol, a base da troca de dados
Web que é o protocolo que permite a obtenção de recursos como por exemplo
documentos HTML, as requisições são feitas a um endereço de web por um usuário que é
o próprio destinatário da informações, o endereço pode assim responder ao destinatário.
Requests tem portanto como objetivo tornar as solicitações HTTP mais amigáveis aos
usuários da linguagem.
65

requests

Pode-se realizar a instalação através do pip rodando o seguinte comando em um terminal:


pip install requests

Para usar a biblioteca deve-se importar o módulo requests:


import requests

A biblioteca requests tem algumas funções mais comuns, elas são:


● Get: faz um pedido de informação a um url e retorna uma resposta a esse pedido.
● Post: manda uma informação a um servidor.
● Delete: faz o pedido para um servidor, para que um dado seja apagado.
Um exemplo de pedido de informação seria:
response = [Link]("[Link]
response = raise_for_status()

O que acontece é o seguinte, a variável response recebe a resposta do pedido feito a


partir da palavra get, que solicita ao endereço especificado entre parênteses por uma
determinada informação.
O endereço usado trata-se de um endpoint de um API Application Programing Interface.
APIs são um conjunto de funções, objetos e protocolos que os programadores podem usar
para desenvolver software interagindo com sistemas externos, um API é a interface entre
você e o sistema externo que você deseja usar. O endpoint é portanto da localização do
dado, que é geralmente um url.
Logo abaixo temos response que recebe raise_for_status() serve para tratar um possível
erro e te retornar um código de erro HTTP caso esse erro tenha ocorrido durante o
processo.
Os erros HTTP podem ser separados em 5 classes básicas:
● 1XX - Resposta não definitiva.
● 2XX - Resposta fornecida com sucesso.
● 3XX - Redirecionamentos.
● 4XX - Erro do cliente.
● 5XX - Erro do servidor.
Onde XX representa um par de números inteiros, para saber de forma mais específica o
erro é necessário pesquisar do que se trata o código de erro mostrado.
66

Exemplo Final 3 - Usando biblioteca gráfica, dados de uma API e


protocolo de e-mail
Neste exemplo temos o uso da biblioteca gráfica tkinter abordada anteriormente a ideia é
um programa simples para organizar os dados mais básicos de um personagem de RPG de
alguns jogadores, o código funciona com uma interface simples, onde é possível cadastrar
jogadores usando o email e um nome do jogador, esses dados ficam salvos e podem ser
consultados usando a própria interface, são então sorteadas, algumas informações da
personagem e essas são enviadas para o email cadastrado.
São importadas as bibliotecas necessárias para o desenvolvimento da aplicação:
from tkinter import *
from tkinter import messagebox
import json
from random import choice
import requests
import smtplib

É criado separado, um arquivo do tipo texto .txt contendo as informações de login do email
que enviará as mensagens, vale lembrar que para que não haja problema com o envio de
emails, as opções de segurança do email devem estar desabilitadas, uma boa opção é criar
um email diferente do seu email pessoal, então o arquivo é aberto usando open() os dados
são copiados do arquivo e o arquivo é fechado usando close():
login = open('[Link]', 'r')
LOGIN_DATA = [[Link](" \n") for line in login]
[Link]()

São criadas as funções para extrair as informações específicas do API escolhido, com seus
respectivos endpoints, os dados são lidos no formato JSON e percorridos como um
dicionário python:
api = "[Link]
def get_race():
response = [Link](api + "/api/races/")
response.raise_for_status()
response = [Link]()["results"]
response = choice(response)
67

É definida uma função para o envio de emails usando o protocolo smtp, a função recebe
como parâmetros o email para onde a informação deve ser enviada e o texto a ser
enviado:
def send_email(email, text):
with [Link]("[Link]") as connection:
[Link]()
[Link](user = LOGIN_DATA[0], password = LOGIN_DATA[1])
[Link](
from_addr = LOGIN_DATA[0],
to_addrs = email,
msg = f"Subject:RPG\n\n{text}"
)

Para manter os dados é criada a função save() que funciona da seguinte maneira, os dados
são armazenados em variáveis e depois organizados no formato de um dicionário, é feito a
confirmação de que está tudo conforme o planejado ou seja, nenhum espaço está vazio no
preenchimento dos dados, caso algo esteja errado isso será mostrado usando o
messagebox, caso esteja correto o preenchimento, outro messagebox é acionado para
confirmar as informações, se essa confirmação é feita, os dados são salvos em um arquivo
JSON, então podem ser consultados usando a função search_site() que pega o nome
cadastrado, a partir de uma entrada da interface do tkinter, e mostra ao usuário as
informações básicas do jogador:
def save():
nome = nome_entry.get()
email = email_entry.get()
personagem = personagem_entry.get()
race = get_race()
classe = get_classe()
new_data = {
nome:{
"Email": email,
"Personagem": personagem,
"Race": race,
"Classe": classe,
}
}
if nome == "" or email == "" or personagem == "":
[Link](title = "Ooops", message = "Certifique-se de
68

não ter deixado nenhum campo em branco.")


else:
is_ok = [Link](title = nome, message = f"Dados
Inseridos: \nEmail: {email}"
f"\nPersonagem: {personagem}"
f"\nRaça: {race}"
f"\nClasse: {}\nIs it ok to save?")

if is_ok:
text = f"Character: {personagem}\n\nRace: {race}\n\nFeastures:
\n{get_race_description(race)}\nClass: {classe}\n\nProficiencies:
\n{get_classe_descriptions(classe,lower())}\n"
send_email(email, text)
try:
with open("[Link]", "r") as data_file:
data = [Link](data_file)
[Link](new_data)
with open("[Link]", "w") as data_file:
[Link](data, data_file, indent = 4)
except FileNotFoundError:
with open("[Link]", "w") as data_file:
[Link](new_data, data_file, indent = 4)
except [Link]:
with open("[Link]", "w") as data_file:
[Link](new_data, data_file, indent = 4)
finally:
nome_entry.delete(0, END)
personagem_entry.delete(0, END)

def search_site():
nome = nome_entry.get()
try:
with open("[Link]", "r") as data_file:
data = [Link](data_file)
except FileNotFoundError:
[Link](title="Not Found", message="Data does not
exist.")
except [Link]:
[Link](title="Not Found", message="Data does not
exist.")
else:
try:
69

search_data = data[nome]
print(search_data)
except KeyError:
[Link](title="Not Found", message="Name not
found.")
else:
[Link](title="Personagem Info", message=f"Nome:
{nome}\nEmail: {search_data['Email']}\nPersonagem:
{search_data['Personagem']}")
finally:
nome_entry.delete(0, END)
personagem_entry.delete(0, END)

Aqui é montada a interface usando as ferramentas do tkinter, são adicionadas uma


imagem, os botões e os espaços de texto:
window = Tk()
[Link]("RPG")
[Link](padx=50, pady=50)

canvas = Canvas(height=200, width=200)


logo_img = PhotoImage(file="[Link]")
canvas.create_image(100, 100, image=logo_img)
[Link](row=0, column=1)

#Labels
nome_label = Label(text="Nome:")
nome_label.grid(row=1, column=0)
email_label = Label(text="Email: ")
email_label.grid(row=2, column=0)
personagem_label = Label(text="Personagem:")
personagem_label.grid(row=3, column=0)

#Entries
nome_entry = Entry(width=40)
nome_entry.grid(row=1, column=1, columnspan=1)
nome_entry.focus()
email_entry = Entry(width=50)
email_entry.grid(row=2, column=1, columnspan=2)
email_entry.insert(0, "@[Link]")
personagem_entry = Entry(width=40)
70

personagem_entry.grid(row=3, column=1)

#Buttons
add_button = Button(text="Add", width=45, command=save)
add_button.grid(row=4, column=1, columnspan=2)
search_button = Button(text= "Search", command = search_site)
search_button.grid(row = 1, column = 2)

[Link]()

Você também pode gostar