Apostila - Módulo 1 - Bootcamp Desenvolvedor (A) Python
Apostila - Módulo 1 - Bootcamp Desenvolvedor (A) Python
Apostila - Módulo 1 - Bootcamp Desenvolvedor (A) Python
2022
Fundamentos de Desenvolvedor(a) Python
Bootcamp Desenvolvedor(a) Python
Antônio Carlos de Nazaré Júnior
© Copyright do Instituto de Gestão e Tecnologia da Informação.
Todos os direitos reservados.
2
Sumário
Listas .......................................................................................................................... 78
3
Conjuntos ................................................................................................................... 88
Dicionários ................................................................................................................. 94
Referências………………………………. ..................................................................................130
4
Capítulo 1. Introdução ao Python
Python é uma linguagem livre e moderna, criada por Guido van Rossum em
1991, e tem como um dos maiores diferenciais a facilidade de aprender, por causa do
seu código limpo e organizado. A linguagem é bastante versátil, sendo empregada no
desenvolvimento de soluções em diversas áreas, como Ciência de Dados e Programação
WEB. Adicionalmente, a demanda por desenvolvedores Python é muito alta, afinal, é a
linguagem de programação mais popular entre os desenvolvedores do mundo todo1.
Muitas pessoas acreditam que o nome Python tem alguma relação com a
espécie de cobra com o mesmo nome (píton, em português), até mesmo porque o
logotipo do Python é composto por duas cobras, uma azul e outra amarela. Entretanto,
segundo a documentação oficial2, o nome foi uma homenagem ao grupo humorístico
britânico Monty Python, do qual o criador da linguagem, Guido van Rossun, era fã.
Assim, quando estava desenvolvendo a linguagem, ele pensou que precisava de um
nome que fosse curto, único e misterioso. Assim, nomeou o projeto de Python.
1
De acordo com o ranking da empresa TIOBE, especializada em avaliação de softwares (TIOBE, 2022).
2
https://docs.python.org/3/faq/general.html
5
Características da Linguagem
De acordo com Sebesta (SEBESTA, 2018), o Python pode ser classificado como
uma linguagem de alto-nível, interpretada, com tipagem dinâmica e multiparadigma. A
seguir, iremos discutir cada uma destas características.
6
Vantagens e Desvantagens
Vantagens
7
O principal lema da linguagem é “Fazer mais, com menos código!”,
o que significa construir protótipos de soluções e testar ideias
muito mais rapidamente em Python do que em outras linguagens.
Prototipação e
Ou seja, sua utilização não apenas economiza muito tempo, mas
Produtividade
também aumenta a produtividade e reduz os custos de
desenvolvimento.
Desvantagens
3
Bibliotecas são coleções de códigos que podem ser distribuídas e reaproveitadas em diversos projetos.
8
Como visto anteriormente, Python é uma linguagem interpretada e
dinamicamente tipada, o que a torna poderosa em diversos
aspectos. Entretanto, esta natureza versátil dela, é também motivo
para que ela não tenha o mesmo desempenho computacional de
outras linguagens populares. Determinados algoritmos, quando
escritos em linguagens como Java ou C++, podem ser executados
Limitações de em até centenas de vezes mais rápidos (SHAW, 2018).
Desempenho
Mas se velocidade de execução não for o requisito mais importante
para o seu projeto, o Python ainda poderá ser uma ótima escolha.
Além disso, existem diversas maneiras de se otimizar o código para
aumentar, consideravelmente, o desempenho computacional
(SLATKIN, 2016).
4
Garbage collector (GC) é um processo interno do Python para automação do gerenciamento de
memória, possibilitando recuperar uma área de memória inutilizada por um programa (SALES, 2020).
9
Python não possui desenvolvimento nativo para plataformas
móveis. Os principais sistemas operacionais deste ambiente,
Android e iOS, não suportam Python como linguagem de
programação oficial, criando assim uma limitação para os
desenvolvedores que desejam utilizar suas aplicações em
Dispositivos smartphones e smartwatches.
Móveis
Ainda assim existem ferramentas que permitem este tipo de
utilização, entretanto requerem um esforço adicional. O exemplo
mais notável é o Kivy5, que permite a compatibilidade de aplicações
Python com diferentes plataformas móveis.
5
Página do projeto Kivy: https://kivy.org
6
GIL é um mecanismo adotado em linguagens interpretadas, como o Python, para o gerenciamento de
execução de threads.
10
Preparação do Ambiente Python
Como vimos, uma das vantagens do Python é a sua portabilidade. Por ser uma
linguagem de programação cross-platform, ela pode ser executada em várias
plataformas, como os sistemas operacionais Windows, macOS e Linux e em distintas
arquiteturas como desktops (32 ou 64 bits) e dispositivos embarcados como o raspberry.
Apesar de não ser o foco do curso, pois utilizaremos uma ferramenta online
com o Python já configurado, nesta seção iremos indicar os passos para a instalação do
Python, em diferentes sistemas operacionais.
SISTEMA TUTORIAIS
7
O Anaconda é gratuito para utilização individual. O download, assim como as instruções de instalação,
para cada sistema operacional está disponível na página do projeto: https://www.anaconda.com
8
Os tutoriais indicados são dos websites (REAL PYTHON, 2020) e (PYTHON BRASIL, 2022), foram escolhidos
por serem simples, mas ao mesmo tempo completos.
11
How to Install Python on Windows (inglês):
https://realpython.com/installing-python/#how-to-install-python-on-
Windows windows
Instalando o Python 3 no Windows (português):
https://python.org.br/instalacao-windows/
How to Install Python on Linux (inglês):
https://realpython.com/installing-python/#how-to-install-python-on-
Linux linux
Instalando o Python no Linux (português):
https://python.org.br/instalacao-linux/
How to Install Python on macOS (inglês):
https://realpython.com/installing-python/#how-to-install-python-on-
MacOs macos
Instalando o Python no Mac OS (português):
https://python.org.br/instalacao-mac/
12
Outra maneira de executarmos um código Python é o modo de script. Em que
escrevemos todo o código em um arquivo texto, com a extensão .py, e em seguida o
executamos por meio do comando:
python arquivo.py
9
https://code.visualstudio.com/
10
https://www.jetbrains.com/pt-br/pycharm/
11
https://atom.io/
12
https://www.sublimetext.com/
13
Google Colab
Para utilizar esta ferramenta, basta ter uma conta ativa do Google, acessar o
endereço do serviço: https://colab.research.google.com/ e em seguida clicar em Novo
notebook, conforme a imagem abaixo. Também é possível explorar o notebook de boas-
vindas, que é sempre aberto ao acessar este endereço. Ele possuiu um tutorial de
introdução dos principais conceitos do Colab.
14
Uma vez que criarmos um notebook, já estaremos prontos para escrevermos e
executarmos o nosso primeiro código, conforme a próxima seção. A ferramenta
também permite que você salve os seus notebooks (ou seja, os seus arquivos de códigos)
diretamente no Google Drive13, para que você possa acessá-los posteriormente.
Uma vez que agora já sabemos como entrar no Google Colab, podemos então
escrever e executar o nosso primeiro código. Para tanto, vamos utilizar as células do
13
Google Drive é o serviço de armazenamento gratuito do Google: https://drive.google.com/
15
notebook que criamos. Digite na primeira célula o seguinte código (ou fiquem à vontade
para copiar e colar):
16
enter" (ou "cmd + enter" em computadores com MacOs). Após a execução teremos a
seguinte saída:
17
Capítulo 2. Escrita de Códigos em Python
A Sintaxe da Linguagem
14
Pseudocódigo é uma forma de representação de algoritmos, escrito em português ou em outro idioma,
que, posteriormente, podem ser transcritos para uma linguagem de programação.
18
Neste capítulo, iremos discutir apenas aspectos da sintaxe do Python. A
semântica (significado das palavras e dos símbolos), serão apresentados
detalhadamente nos capítulos e seções seguintes.
Resultado final
menores: [0, 1, 2, 3, 4]
maiores: [6, 7, 8, 9]
Comentários
15
Exemplo de código adaptado de (VANDERPLAS, 2016).
19
Comentários são trechos de códigos que são ignorados pelo interpretador da
linguagem. O uso de comentários auxilia na documentação do programa, pois fornece
algumas informações e/ou orientações sobre o seu funcionamento. Imagine você,
escrevendo um código complexo hoje e tendo que entendê-lo daqui cinco anos? Tenho
certeza de que o seu "eu" do futuro irá te agradecer se você documentar este código!
Quebras de Linhas
limiar = 5↵
20
Indentação
for i in range(10):
#indentação indicando bloco
in (i < limiar):
#indentação indicando um outro novo bloco
menores.append(i)
21
consistente em todo o código. Ou seja, devemos utilizar a mesma quantidade de espaços
em branco para indentar todos os blocos em nosso código. Por convenção, a maioria
dos especialistas recomendam utilizar quatro espaços para realizar a indentação, e,
portanto, adotaremos esta convenção em todo o nosso curso.
fim 4
fim
22
limiar = 5
limiar=5
limiar = 5
Utilização de Parênteses
x = 2 * (3 + 4)
y = (5 - 2) * (3 + 4)
z = (x + y) * 3
a = (x + y) / z
Os parênteses também podem ser utilizados para indicar que uma função
deverá ser chamada16. Por exemplo, no código de exemplo no início desta seção, a
função print foi chamada para exibir a frase "Resultado final" na tela. A chamada de
funções é iniciada por um parêntese de abertura, seguido pelos argumentos9 da função
e finalizada por um parêntese de fechamento, conforme os exemplos a seguir:
print('Resultado final')↵
print('menores:', menores)↵
print('maiores:', maiores)↵
Algumas funções podem ser chamadas sem nenhum argumento. Neste caso,
os parênteses de abertura e fechamento ainda devem ser utilizados. Um exemplo é a
própria função print, que se chamada sem nenhum argumento, irá exibir apenas uma
linha em branco:
16
Veremos os detalhes sobre funções e argumentos no Capítulo 6.
23
... print()
... print('linha 2')
linha 1
linha 2
Variáveis e Keywords
variavel = valor
24
var_booleano = True
raio = 2
pi = 3.14159265359
Observe que não foi necessário realizar uma declaração explícita do tipo ao
qual pertence cada variável, apenas foi declarado o valor (ou a expressão que resultará
em um valor). Esta característica faz com o que o Python seja uma linguagem
dinamicamente tipada, onde os tipos de variáveis são inferidos durante a execução do
programa.
● Uma variável pode conter letras e números, mas não pode começar com um
número. Portanto, variavel1 e var1avel são nomes válidos, enquanto 1variavel é
inválido.
25
● É permitido utilizar letras minúsculas e maiúsculas para nomes de variáveis.
Entretanto, é recomendável utilizar apenas letras minúsculas. É importante
ressaltar que Python é case sensitive, ou seja letras maiúsculas e minúsculas, são
diferentes para o interpretador. Assim nome e Nome são duas variáveis
diferentes, pois uma começa com letra minúscula e a outra começa com uma
letra maiúscula.
Por fim, existe também um conjunto de palavras que são reservadas do Python
e por isso não podemos utilizá-las como nomes de variáveis. Este conjunto é chamado
de keywords (palavras-chaves) e são palavras que já possuem alguma função pré-
estabelecida na linguagem. É importante ressaltar que keywords também são case
sensitive (diferencia letra maiúscula de minúscula). A seguir são apresentadas as
principais keywords do Python.
26
False None True and as assert async
Erros de Sintaxe
27
>>> x=3
... y=5
... print x + y
x=3
1var = x
y=5
print x + y
28
... dia = 'Segunda Feira'
... print(Dia)
>>> x=0
... 25 / x
Erros Lógicos
O tipo de erro mais difícil de lidar em Python é o chamado erro lógico. Por
exemplo, considere que um desenvolvedor deseja calcular a média entre três variáveis
(x, y e z), com os seus respectivos valores (x=2.0, y=7.0, z=12.0). Para tanto ele escreve
o código abaixo:
>>> x = 5.0
... y = 7.0
... z = 12.0
... media = x + y + z / 3
... print(media)
16.0
Observe que, por não ter nenhuma regra violada, o interpretador foi capaz de
executar todas as instruções e retornar 16.0, que por usa vez não é a média dos números
5.0, 7.0 e 12.0. A resposta correta deveria ser 8.0. Este erro é devido à ordem de
29
execução das operações. Primeiramente, o valor de z foi dividido por três, resultando
em 4.0 e em seguida somado com x e y: media = 5.0 + 7.0 + 4.0 => 16.0. O correto seria
indicar a precedência das somas, utilizando parênteses, e em seguida dividir por 3.
>>> x = 5.0
... y = 7.0
... z = 12.0
... media = (x + y + z) / 3
print(media)
8.0
Erros como este podem custar muito caro. Imagine, por exemplo, se um
software de um banco calculasse de forma errada o somatório de todos os depósitos de
um cliente? Felizmente, para evitar comportamentos inesperados, existem técnicas de
teste de software que devem ser aplicadas em projetos do mundo real e que irão
identificar estes tipos de erro antes do programa ser utilizado para valer.
30
Capítulo 3. Tipos Primitivos de Dados e Operadores
31
Tipos Primitivos de Dados em Python
O Python oferece quatro tipos primitivos de dados (int, float, boolean, string),
que definem o tipo mais genérico possível da informação que um valor carrega. Estes
tipos primitivos serão apresentados a seguir:
32
O int (inteiro) é um tipo composto por caracteres numéricos
(algarismos), utilizado para representar um número que pode ser escrito
sem um componente decimal, podendo ter ou não sinal, isto é, ser
int positivo ou negativo. Os valores do tipo inteiro podem ter um tamanho
ilimitado.
Números
Inteiros x=3
x = -3
y=-
5233423523098508258245824580924386092433850247459824986
72348
O float (flutuante) também é composto por caracteres numéricos, mas é
utilizado para representar números racionais (números que podem ser
escritos como frações), também conhecidos como ponto flutuante17.
Assim como os inteiros, podem ter sinal ou não e possuem um tamanho
float ilimitado. As casas decimais são separadas da porção inteira por um
Números ponto (.).
Racionais
x = 3.5
x = -3.583344082
pi =
3.141592653589793238462643383279502884197169399375105820
9749
O bool é um tipo de dado lógico que pode assumir apenas dois valores:
falso ou verdadeiro (False ou True, respectivamente, em Python). Na
bool lógica computacional, podem ser considerados como 0 (falso) ou 1
(verdadeiro). É um tipo de dado muito útil para a verificação de
Booleano
s condições, conforme será apresentado no Capítulo 4.
x = True
y = False
Por fim, o str (abreviação de string, que em português podemos traduzir
como cadeia de caracteres) é uma sequência/cadeia de caracteres
str utilizada para representar palavras, frases ou textos. As strings18 podem
Sequênci ser declaradas de diferentes formas, por meio de aspas simples ('), aspas
a de duplas (") ou tripla de aspas (''') – três aspas simples consecutivas.
Caractere
s x = 'aspas simples'
y = "aspas duplas"
z = '''aspas simples'''
33
Diferentemente das regras para nomes de variáveis que vimos no capítulo
anterior, podemos utilizar qualquer caractere Unicode19 para os valores de uma string.
Isso significa que podemos ter strings com caracteres japoneses (kanji), caracteres
coreanos (hangul) e, principalmente, os caracteres especiais que utilizamos na língua
portuguesa.
exemplo_kanji = 'キャラクター例'
exemplo_hangul = '문자 예'
exemplo_português = 'programação'
17
Em termos gerais, Ponto Flutuante, do inglês floating point, é um formato de representação dos
números racionais, que é utilizada na lógica digital dos computadores (OVERTON, 2001).
18
Por uma questão de padronização, utilizaremos o termo string para se referir à uma sequência de
caracteres, pois é o termo utilizado por desenvolvedores do mundo todo, independente do idioma.
19
O alfabeto Unicode possuí mais de 1 milhão de caracteres e é um único conjunto de caracteres contendo
os idiomas de todo o mundo (https://home.unicode.org/).
34
Por fim, as triplas de aspas permitem a declaração de sequências com várias
linhas, conforme o exemplo abaixo. Todos os espaços em branco declarados, assim
como as quebras de linha, serão inclusos no valor da string.
35
Este tipo de dados especial é utilizado para representar um valor nulo.
Em algumas situações, pode ser necessário termos uma variável sem
NoneType nenhum valor ou ainda indefinida. É para esses casos que utilizaremos
tipo NoneType. Em Python, o valor nulo é representado pela palavra-
Valores
Nulos chave None, conforme o exemplo:
x = None
y = None
A função type()
>>> x = 10
... print(type(x))
<class 'int'>
>>> y = 'palavra'
... print(type(y))
<class 'str'>
>>> print(type(3.59))
36
<class 'float'>
>>> print(type(True))
<class 'bool'>
>>> z = None
... print(type(z))
<class 'NoneType'>
Esta função é importante para caso seja necessário verificar o tipo de um dado
em específico. Nas próximas seções utilizaremos o método type() para ilustrar alguns
conceitos.
Operadores Aritméticos
O Python possuí sete operadores aritméticos que são utilizados para realizar
operações matemáticas como adição, subtração e multiplicação. São eles:
37
OPERAÇÃO DESCRIÇÃO UTILIZAÇÃO
+ Adição Adiciona os valores dos dois operandos. x+y
Subtrai do operando esquerdo o valor do
- Subtração x-y
operando direito.
* Multiplicação Multiplica os valores dos dois operandos. x*y
Divide o operando esquerdo pelo valor operando
/ Divisão da direita. O resultado será sempre um número x/y
racional (float).
Módulo (resto) da divisão do operando esquerdo
% Módulo pelo da direita. O resultado será um número x%y
inteiro (int).
Divisão inteira do operando da esquerda pelo
Divisão operando da direita. Retorna apenas a parte
// x // y
Inteira inteira do resultado da divisão tradicional. O
resultado será sempre um número inteiro (int).
Realiza a exponenciação (potenciação) do
Exponenciaçã
** operando da esquerda, elevando-o a potência do x ** y
o
operando da direita.
Enquanto para alguns operadores o tipo de dado do resultado é fixo (/, % e //),
para outros o resultado dependerá do tipo dos operandos (+, -, * e **). Por exemplo, o
resultado da adição (+) de dois operandos do tipo inteiro (int) é um outro inteiro.
Entretanto, se um dos operandos for do tipo racional (float), o resultado também será
do tipo float:
<class 'int'>
<class 'float'>
Uma vez que o tipo bool assume os valores True ou False, que matematicamente
são representados por 1 e 0 (respectivamente), os operadores aritméticos também
podem ser aplicados ao tipo booleano:
38
>>> print(10 + False) # Equivale a 10 + 0
... print(True + 5) # Equivale a 1 + 5
... print(True + True + False) # Equivale a 1 + 1 + 0
10
6
2
>>> x = 10
... y=4
... z = 4.5
... print('x + y + z=', x + y + z)
... print('x - 3 =', x - 3)
... print('x * z =', x * z)
... print('x * 2 =', x * 2)
... print('x / (y + 2) =', x / (y + 2))
... print('x % y =', x % y)
... print('x // y =', x // y)
... print('x ** z =', x ** z)
x + y + z = 18.5
x-3=7
x * z = 45.0
x * 2 = 20
x / (y + 2) = 1.666666666666
x%y=2
x // y = 2
x ** z = 31622.776601683792
P Parênteses
E Exponenciação
M Multiplicação
39
D Divisão
A Adição
S Subtração
(𝐵 + 𝑏) × ℎ
𝑎𝑟𝑒𝑎 =
2
Para 𝐵 = 15, 𝑏 = 10 e ℎ = 8 temos:
(15 + 10) × 8
𝑎𝑟𝑒𝑎 = = 100
2
40
O erro foi causado pela ordem em que as operações foram realizadas, que,
segundo a regra apresentada anteriormente (PEMDAS), foi a seguinte:
4. Por fim, a adição (15 + 40) será realizada, resultando no valor de 55.
>>> area = (B + b) * h / 2
... print('Área do Trapézio: ', area)
Operadores de Comparação
Essa categoria de operadores é utilizada para comparar valores entre si. Eles
também são chamados de operadores relacionais e sempre retornaram um resultado
do tipo booleano (bool), com o valor True ou False, de acordo com a condição avaliada.
41
Verdadeiro (True) se os dois operandos são
== Igual x == y
iguais (possuem o mesmo valor).
Verdadeiro (True) se os dois operandos são
!= Diferente x != y
diferentes (não possuem o mesmo valor).
Estes operadores podem ser utilizados para todos os tipos primitivos de dados
do Python, inclusive em conjunto com os operadores aritméticos, como podemos ver
nos exemplos a seguir:
>>> x=5
... y=1
... s = 'palavra'
...
... print('x > y:', x > (y + 2))
... print('x <= 4.564:', x <= (4.564 + 1))
... print('s == palavra:', s != 'palavra')
... print('(y * 0) == False:', (y * 0) == False)
... print('s != abacaxi:', s != 'abacaxi')
x > y: True
x <= 4.564: True
s == palavra: False
(y * 0) == False: True
s != abacaxi: True
>>> x=3
... y = 'palavra'
... print(x == y)
... print(x != y)
... print(x > y)
False
True
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-45-19a87f04b970> in <module>()
42
3 print(x == y)
4 print(x != y)
----> 5 print(x > y)
>>> a = 'casa'
... b = 'predio'
... c = 'elevador'
... d = 'casamento'
... print(x < y)
... print(x > z)
... print(y > z)
... print(a > d)
... print('abacaxi' >= 'abacaxi')
True
False
True
False
False
Operadores Lógicos
Os operadores lógicos, como o próprio nome diz, são operadores que permitem
realizar operações lógicas entre valores booleanos e o resultado será sempre verdadeiro
(True) ou falso (False). Estes operadores são importantes para a formação de lógicas
completas, em conjunto com outros operadores, que possibilitam a verificação de
diferentes condições no programa. Fazem parte desta categoria os seguintes
operadores lógicos:
43
OPERAÇÃO DESCRIÇÃO UTILIZAÇÃO
an Verdadeiro (True) se, e somente se, os dois
Conjunção x and y
d operandos também forem verdadeiros.
Verdadeiro (True) se qualquer um dos dois
or Disjunção x or y
operandos for verdadeiro também.
Inverte o valor do operando (complemento).
Complement
not Verdadeiro (True) se o operando for falso. Falso not x
o
(False) se o operando for verdadeiro.
False
True
44
A B A AND B A OR B NOT A NOT B
True True True True False False
True
True
False
False
c o n s o l a ç ã o
Podemos então enumerar cada uma destas posições, ou seja, podemos atribuir
um índice para cada posição (caractere) da string. Esse processo é conhecido como
45
indexação e em Python, assim como em várias outras linguagens, os índices sempre
começam a partir de zero20:
c o n S O l a ç ã o
0 1 2 3 4 5 6 7 8 9
c o n s o l a ç ã o
0 1 2 3 4 5 6 7 8 9
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1
20
Por esse motivo, Python é conhecido como uma linguagem 0-indexed ou 0-based.
46
apresentados exemplos de uso do operador de acesso aos caracteres da string
'consolação':
Primeiro caractere: c
Segundo caractere: o
Sexto caractere: l
Último caractere: o
Último caractere: o
Penúltimo caractere: ã
Antepenultimo caractere: ç
Primeiro caractere: c
47
estas palavras menores utilizando o conceito de slicing e para um melhor entendimento,
vamos também observar a figura que ilustra os índices da palavra:
consola
sol
sola
ação
consolação
c o n s o l a ç ã o
0 1 2 3 4 5 6 7 8 9
-10 -9 -8 -7 -6 -5 -4 -3 -2 -1
c o n s o l a ç ã o
0 1 2 3 4 5 6 7 8 9
Observe que, para as palavras consola e ação, não foi indicado de forma
explicita o inicio e o fim, respectivamente. Isso é possível, pois o Python identifica que
deverá ser usado o primeiro índice (no caso de omitir o inicio) e o último índice (se fim
48
for omitido). Por fim, se os dois valores forem omitidos, a string original será retornada,
conforme o último exemplo palavra[:];
...
TypeError: string indices must be integers
>>> palavra[99]
...
IndexError: string index out of range
Operadores de Strings
49
A seguir serão apresentados exemplos de utilização dos operadores de
concatenação (+) e repetição (*) de strings:
>>> s1 = 'Belo'
... s2 = 'Horizonte'
...
... # Concatenação (+)
... print(s1 + s2)
... print(s1 + ' ' + s2)
... print(s1 + ' Monte')
...
... # Repetição
... print(s1 * 5)
... print((s1 + ', ') * 4)
BeloHorizonte
Belo Horizonte
Belo Monte
BeloBeloBeloBeloBelo
Belo, Belo, Belo, Belo,
>>> s1 = 'consolação'
... s2 = 'sola'
...
... print(s1 in s2)
... print(s2 in s1)
... print('solar' in s1)
... print('solar' not in s2)
50
False
True
True
True
10
BELO HORIZONTE
belo horizonte
Esta É Uma Frase, Com Uma Vírgula.
Belo Monte
True
False
51
11
>>> print('nome'.upper())
... print('a, b, c, d'.split(','))
... print('Belo Horizonte'.replace('Horizonte', 'Monte'))
NOME
['a', 'b', 'c', 'd']
Belo Monte
52
Isso ocorre porque a concatenação de strings com outros tipos de dados não é
permitida. Felizmente, o Python oferece duas formas de lidarmos com esta situação: a
primeira delas é a conversão dos tipos dados e a segunda é a formatação de strings. A
seguir serão apresentados estes conceitos, assim como exemplos de utilização.
Eu tenho 36 anos
float → bool bool(f) True se o racional f for diferente de 0.0, False se o contrário.
53
O número racional f será convertido para uma string, com
float → str str(f)
uma precisão de 15 casas decimais.
bool → int int(b) Se o valor de b for True será retornado 1. Se False, retorna 0.
54
>>> #conversão do tipo int
... print(float(10)) # 10.0
... print(bool(-1)) # True
... print(bool(0)) # False
...
... #conversão do tipo float
... print(int(9.999)) # 9
... print(bool(-0.99)) # True
... print(str(-0.99)) # '-0.99'
...
... #conversão do tipo bool
... print(int(True)) # 1
... print(float(False)) # 0.0
... print(str(True)) # 'True'
...
... #conversão do tipo str
... print(int('-99')) # 99
... print(float('0.01')) # 0.00001
... print(bool('palavra')) # True
... print(bool('')) # False
10.0
True
False
9
True
-0.99
1
0.0
True
-99
0.01
True
False
55
>>> x = 10
... print('Valor:', x, '--', type(x))
...
... # atribuição do valor None à variável x
... x = None
... print('Valor:', x, '--', type(x))
Por sua vez, a conversão do valor None para outros tipos é possível apenas para
os tipos str e bool. Enquanto a conversão de None para uma string resulta na string
'None', a conversão do valor None para o tipo bool sempre retornará False.
>>> print(str(None))
... print(bool(None))
'None'
True
Formatação de Strings
Uma outra forma de criarmos uma string a partir de diferentes tipos de dados
é a utilização do conceito de formatação de strings. O Python possibilita três formas de
formatarmos uma string:
• A utilização do operador %;
• O método str.format();
21
Recomendação de materiais sobre o operador % e o método str.format():
56
que o f-strings é recente, muitos códigos encontrados em repositórios, outros cursos e
artigos ainda podem utilizar estes conceitos.
Eu tenho 36 anos
Neste caso, o valor da variável idade foi utilizado no lugar da declaração {idade}.
E não precisamos nos limitar apenas à utilização de variáveis, podemos utilizar também
expressões que irão resultar em valores a serem interpolados na string. Poderíamos
simplificar o código acima, suprimindo o uso da variável idade, da seguinte maneira:
Eu tenho 36 anos
• https://realpython.com/python-f-strings/
• https://programadorviking.com.br/metodo-format-em-python/
• https://pyformat.info/
57
Também podemos utilizar métodos e funções dentro de f-strings, como por
exemplo:
Por fim, é possível realizar alguns tipos de formatações nos valores antes da
interpolação na string resultante. Por exemplo, considere que queremos exibir a
porcentagem gasta de um determinado orçamento:
58
... vlr_gasto = 430
... pct = (vlr_gasto/orcamento)
... print(f'Porcentagem já gasta do orçamento: {pct:.2%}')
59
Capítulo 4. Fluxos de Controle em Python
Estes são apenas alguns exemplos, sendo que existem diversos outros
problemas em que é necessário projetarmos soluções com tarefas de seleção e
repetição, em que muitas das vezes estão condicionadas aos valores de um certo
conjunto de dados.
60
realizado por meio de estruturas condicionais, estruturas de repetição e funções
(MARTELLI, RAVENSCROFT e HOLDEN, 2017).
Estruturas Condicionais
Em outras palavras, estas condições deverão ser verificadas com base nos
dados de entrada e em seguida as ações (instruções) serão executadas de acordo com a
condição ser verdadeira ou não. Em Python existem três tipos de estruturas
condicionais, que veremos a seguir.
Estrutura Condicional if
61
if <expressão>:
<bloco de código se a expressão é verdadeira>
Observe que a condição idade > 18 é formada por uma expressão que utiliza o
operador condicional maior que (>=). Como mencionado anteriormente, é possível
combinarmos diferentes expressões para criar uma condição:
62
>>> # Verifica se uma pessoa está apta para se aposentar
... idade = 70
... tempo_contrib = 20
... if idade >= 65 or tempo_contrib >= 35:
print('Habilitado para solicitar aposentadoria!')
Neste último exemplo utilizamos o operador lógico or, para verificar se pelo
menos uma das expressões (idade >= 65 ou tempo_contrib >=35) eram verdadeiras.
Como a idade indicada é maior ou igual que 65, a condição é verdadeira e a mensagem
foi exibida.
if <expressão>:
<bloco de código se a expressão é verdadeira>
else:
<bloco de código se a expressão é falsa>
63
Podemos observar, pela sintaxe, que essa estrutura é semelhante à instrução if
simples, mas adiciona outro bloco de código que será executado caso a condição não
seja verdadeira. A seguir veremos alguns exemplos de utilização da instrução if – else, a
partir de variações dos códigos da seção anterior.
Neste exemplo, foi adicionado uma nova mensagem após a instrução else. Se a
condição idade >= 18 for verdadeira, a primeira mensagem será exibida, caso contrário,
a segunda mensagem que será exibida. Vejamos o mesmo exemplo, mas com a condição
sendo falsa:
64
Outra possibilidade também, dependendo da aplicação, é a utilização de
estruturas condicionais aninhadas, ou seja, if - else dentro de if – else. Por exemplo,
estrutura condicional anterior poderia ser reescrita da seguinte maneira:
22
Exemplo adaptado de (DEVMEDIA, 2022).
65
a sua faixa etária. Observe que a cada instrução else, uma nova condição é verificada a
seguir com outra instrução if. Isso deixa o código confuso, diminuindo a sua legibilidade.
Para estes casos, podemos utilizar a estrutura condicional if - elif – else. Essa é
uma variação da estrutura condicional if – else, onde a instrução elif é empregado para
avaliar as expressões intermediárias, sendo adicionada entre as instruções if e else, de
tal forma que podem ser acrescentados quantas condições forem necessárias.
if <expressão 1>:
<bloco de código se a expressão 1 é verdadeira>
elif <expressão 2>:
<bloco de código se a expressão 2 é verdadeira>
elif <expressão 3>:
<bloco de código se a expressão 2 é verdadeira>
else:
<bloco de código se nenhuma expressão é verdadeira>
66
... faixa_etaria = 'Adolescente'
... elif idade < 60:
... faixa_etaria = 'Adulto'
... else:
... faixa_etaria = 'Idoso'
... print('Faixa Etária: ', faixa_etaria)
Neste exemplo, é definido a primeira condição (idade < 12). Caso essa condição
seja falsa, o programa seguirá para a avaliação da próxima condição (elif idade < 18),
que se for verdadeira fará com que o bloco logo abaixo (faixa_etaria = 'Adolescente')
seja executado. Caso essa condição ainda não seja atendida, a próxima condição (elif
idade < 60) será verificada. Por fim, se nenhuma das condições for verdadeira, o
programa seguirá para o bloco de código definido pelo else (faixa_etaria = 'Idoso').
Estruturas de Repetição
67
Estrutura de Repetição while
while <expressão>:
<bloco de código a ser repetido enquanto a expressão for verdadeira>
Após a declaração do while é sempre necessário definir uma condição que será
verificada antes de cada execução do bloco de código, e o loop somente será
interrompido quando essa condição não for mais verdadeira.
68
... contador = 0
...
... while contador <= n:
... soma = soma + contador
... contador = contador + 1
...
... print(f'A soma dos primeiros {n} inteiros é {soma}')
Observe que foi utilizado uma variável auxiliar, chamada contador, responsável
por controlar quais inteiros já foram somados ou não. Assim, a condição contador <= n
será verdadeira enquanto o valor de contador não for maior que n. Enquanto esta
condição for verdadeira, a variável soma vai acumulando o somatório dos números e o
contador vai sendo incrementado em uma unidade. Uma vez que o contador seja maior
que n, o loop é interrompido. É possível reescrever o código, sem o uso da variável
auxiliar contador, utilizando o próprio n como variável de controle.
69
apresentamos apenas uma sequência iterável: o tipo de dados string. Entretanto, outros
tipos de dados não-primitivos, que também são iteráveis, serão apresentados no
Capítulo 5.
Sequências que contém inteiros consecutivos são muito comuns e, por esta
razão, o Python fornece uma maneira bem simples para a sua criação: a função range,
que possui a seguinte sintaxe:
70
Essa função permite criar uma faixa (range) de números inteiros, começando
por inicio e finalizando com fim – 1 (o valor de fim não é incluído na sequência
resultante). O valor de incremento indica o incremento que será adicionado entre um
item e outro. Os argumentos inicio e incremento são opcionais (ou seja, não precisam
ser declarados), e por padrão a sequência irá iniciar no número 0 e ser incrementada em
1. Vejamos alguns exemplos de utilização da função range.
# 0, 1, 2, 3, 4
range(5)
# 3, 4, 5, 6, 7
range(3, 8)
# 0, 5, 10, 15, 20
range(0, 21, 5)
# 2, 4, 6, 8
range(2, 10, 2)
Em conjunto com a estrutura de repetição for … in, a função range pode ser
utilizada para executar um determinado bloco de código, pela quantidade de vezes
indicadas na função range. Por exemplo, o problema de determinar a soma dos
primeiros n números inteiros, poderia ser solucionado da seguinte forma:
Observe que foi necessário utilizar a função range com n+1 (range(n + 1). Se
fosse utilizado apenas n como argumento (range(n)), o resultado seria a soma de apenas
os 14 primeiros inteiros, e não os 15 primeiros como pretendido.
71
Interrupção da Estruturas de Repetição
72
if <condição de parada>
<outro bloco de código>
break
73
Capítulo 8. Estruturas de Dados
Vejamos uma situação prática do mundo real. Considere que estamos criando
um software para processar o IPTU de todos os imóveis da cidade de Belo Horizonte e
para isso criaremos uma variável simples para representar cada imóvel. Os mais atentos
já devem ter percebido que seria uma tarefa quase impossível criar centenas de milhares
de variáveis, pois esta é a dimensão de imóveis em Belo Horizonte.
74
primitivos, as estruturas de dados possuem operadores e métodos que podemos utilizar
para acessar e manipular os valores que estão contidos nelas.
Maior idade: 49
75
No exemplo anterior foram utilizados então, para três pessoas, três variáveis, e
foram realizadas três comparações. Parece simples, certo? Vamos avançar o problema
então e agora vamos considerar um grupo maior de quatro pessoas.
if p1 >= p2:
if p1 >= p3:
if p1 >= p4:
print('Maior idade:', p1)
else:
print('Maior idade:', p4)
elif p3 >= p4:
print('Maior idade:', p3)
else:
print('Maior idade:', p4)
if p2 >= p3:
if p2 >= p4:
print('Maior idade:', p2)
else:
print('Maior idade:', p4)
elif p3 >= p4:
print('Maior idade:', p3)
else:
print('Maior idade:', p4)
76
Podemos observar que, mesmo com um pequeno número de pessoas, é
totalmente inviável implementar esta estratégia de utilizar variáveis simples. Por
exemplo, ao adotar esta estratégia para um grupo de 35 pessoas, um desenvolvedor
habilidoso (que consegue escrever uma comparação por segundo) gastaria mais de 550
anos. Ou seja, mesmo se ele tivesse iniciado a escrita código no dia que Cabral descobriu
o Brasil, ele ainda não teria terminado! E nem estamos considerando o tempo
necessário para executar o programa, que também demoraria muito.
Em Python não poderia ser diferente, pois contamos com estruturas de dados
que, juntamente com algoritmos já implementados na linguagem, oferecem formas
otimizadas de acesso e processamento de uma coleção extensa de valores. As quatro
estruturas de dados principais do Python são:
77
valor cujo estado interno pode ser alterado é mutável. Por outro lado, imutável não
permite nenhuma alteração no valor depois de criado.
Listas
Em Python, uma lista (list) é uma sequência ordenada de valores, que são
identificados por um índice. Estes valores, que compõem uma lista, são chamados de
elementos ou itens. Listas são estruturas de dados muito similares às strings, que por
sua vez são sequência de caracteres, apenas. A diferença é que os elementos de uma
lista podem ser de qualquer tipo, ou seja, podem ser homogêneos (todos os valores do
mesmo tipo) e heterogêneos (valores com tipos distintos).
78
A seguir será apresentada formas de criar listas e acessar seus elementos, assim
como os principais métodos que este tipo de dados oferece.
Listas podem ser criadas por meio da declaração de valores separados por
vírgulas e delimitados por colchetes. Por exemplo, o código abaixo cria uma lista dos
primeiros números primos, a lista é homogênea visto que todos elementos são do tipo
int.
>>> [2, 3, 5, 7]
[2, 3, 5, 7]
[]
23
Quando isso ocorre, pode-se dizer que são listas aninhadas.
79
De forma semelhante ao acesso dos caracteres de uma string (Seção Operador
de Acesso das Strings), a sintaxe para acessar os elementos de uma lista é por meio do
operador ([]), especificando o índice (posição) do elemento a ser acessado (ex.: [0] e l[1])
e sempre com o primeiro elemento no índice 0. Também podemos utilizar índices
negativos e o conceito de slicing (faixa de índices), que nos retorna uma sub-lista.
2
True
casa
['a', 5.44, True]
[None, 'casa']
[2, 'a', 5.44, True, None, 'casa']
Agora que aprendemos a criar listas, e acessar seus elementos, que tal
reescrevermos o exemplo da seção anterior utilizando uma lista? Para um exemplo
inicial, considere o mesmo problema apresentado inicialmente: encontrar o maior idade
entre um grupo de três pessoas. Podemos então criar uma lista com três elementos e,
em seguida utiliza a estrutura de repetição for … in para encontrar o maior valor.
2
True
casa
['a', 5.44, True]
[None, 'casa']
80
[2, 'a', 5.44, True, None, 'casa']
Observe que fizemos uso da estrutura de repetição for … in para iterar a lista,
pois, o tipo list também é uma sequência iterável e a esta estrutura de repetição pode
percorrer qualquer sequência iterável, como aprendemos na Seção Estrutura de
Repetição for … in. O mesmo código pode ser utilizado, também, para um grupo maior
de pessoas. Por exemplo, para 15 pessoas seria necessário apenas modificar a lista
inicial, acrescentando as idades das novas pessoas.
Maior idade: 85
Outra vantagem é que escrevemos apenas uma comparação (if idade >
maior_idade), que será executada 𝑛 vezes, onde 𝑛 é o tamanho da lista a ser processada.
Por exemplo, para encontrarmos a maior idade dentre os habitantes do Brasil
(aproximadamente 212 milhões de pessoas), seriam necessários apenas 4,5 segundos!
Será que existe uma maneira mais legível e eficiente de resolver o problema do exemplo
anterior? A resposta é sim e veremos como na próxima seção!
Nesta seção, veremos diversos recursos úteis do tipo list, que são compostos
por operadores, métodos e funções que manipulam valores destas estruturas de dados.
Iniciaremos com exemplos de como adicionar, alterar e remover elementos das listas.
81
>>> # Criar uma lista inicial, com elementos heterogêneos
... lista = [2, 'a', 'b', 'c', 5.44, True]
... print(lista)
4. Por fim removemos a primeira ocorrência do elemento 'a', por meio do método
remove(elem). Este método remove a primeira ocorrência do elemento elem na
lista. Um erro de execução acontecerá se o elemento elem não pertencer à lista.
24
Apesar de semelhantes, listas e strings possuem uma diferença muito importante. Enquanto as listas
são tipos de dados mutáveis, as strings são imutáveis. Portanto, conseguimos alterar o valor de um
elemento na lista utilizando o operador [], mas não conseguimos fazer o mesmo com aos caracteres de
uma string.
82
De forma semelhante às strings, podemos utilizar os operadores de
concatenação (+), repetição (*) e de filiação (in) com as listas. Também podemos utilizar
funções e métodos. Vejamos a seguir alguns exemplos de operações úteis que são
implementados no Python e que os desenvolvedores utilizam frequentemente.
4
60
30
83
7
3
>>> idades = [27, 49, 12, 67, 21, 32, 18, 45, 84, 53, 22, 56, 80, 35, 18]
... print('Maior idade:', max(idades))
Maior idade: 84
84
E a melhor parte é que esta função é implementada de uma forma tão eficiente
que faz com que encontremos a maior idade dentre os habitantes do Brasil em apenas
7 microssegundos, ou seja, 0,000007 segundos. Bem melhor que os 4,5 segundos da
nossa implementação anterior!
Tuplas
85
... print(tupla2[:])
(0, 1, 2, 3, 4)
(2, 'a', 5.44, True, None)
()
0
3
4
4
10
30
60
2
1
86
Entretanto, uma vez que as tuplas são imutáveis, não existem métodos capazes
de alterar os valores internos dela, como por exemplo append, remove, sort, reverse e
pop e clear. Da mesma forma, a substituição de elementos, por meio do operador de
atribuição (=), não é permitida, como por exemplo tupla[0] = 99. Ao tentar realizar essas
operações, teremos um erro de execução alertando que o tipo tuple não as suportam
>>> t1 = (1, 2, 3)
... t1[0] = 4
Ok, mas se as tuplas são tão semelhantes às listas, ao mesmo tempo que as
listas oferecem uma maior flexibilidade (por serem mutáveis), porque então deveríamos
utilizar tuplas? Mark Pilgrim, em seu livro (PILGRIM, 2009), enumera três pontos
interessante sobre as tuplas, que são transcritas a seguir:
• "Tuplas são mais rápidas que listas. Se você está definindo uma sequência
constante de valores e você vai ter que iterar sobre ele, utilize uma tupla ao invés
de uma lista."
• "Tuplas tornam o seu código mais seguro, uma vez que eles protegem contra
gravações, os dados que não precisam ser alterados. Usar uma tupla em vez de
uma lista é como ter uma declaração implícita de que esses dados são constantes
e que uma função específica será necessária para sobrescrevê-los."
87
• "Tuplas podem ser utilizadas como chaves de dicionários25. As listas nunca
podem ser utilizadas como chaves de dicionário, porque as listas não são
imutáveis."
Conjuntos
25
Para os novatos, talvez o último ponto seja confuso, mas vocês entenderão daqui a pouco quando
conhecermos as estruturas de dados do tipo dicionário.
88
... print(c2)
...
... # Conjunto heterogêneo
... c3 = {2, 'a', 5.44, True, None}
... print(c3)
{0, 1, 2, 3, 4}
{0, 1, 2, 3, 4}
{True, 2, 5.44, None, 'a'}
Para tornar mais clara a utilidade das estruturas de dados deste tipo, iremos
conhecer as principais operações dos conjuntos. Mas, antes, vale a pena revisitarmos
como essas operações matemáticas são realizadas, conforme a figura26 abaixo:
26
Imagens adaptadas de (PAREWA LABS PVT. LTD., 2022)
89
... B = {4, 5, 6, 7, 8}
... print('A:', A)
... print('B:', B)
...
... # Operação de União: (A ∪ B)
... print('A | B =>', A | B)
... print('A.union(B) =>', A.union(B))
...
... # Operação de Interseção: (A ∩ B)
... print('A & B =>', A & B)
... print('A.intersection(B) =>', A.intersection(B))
...
... # Operação de Diferença: (A - B) e (B - A)
... print('A - B =>', A - B)
... print('A.difference(B) =>', A.difference(B))
... print('B - A =>', B - A)
... print('B.difference(A) =>', B.difference(A))
A: {1, 2, 3, 4, 5}
B: {4, 5, 6, 7, 8}
A | B => {1, 2, 3, 4, 5, 6, 7, 8}
A.union(B) => {1, 2, 3, 4, 5, 6, 7, 8}
A - B => {1, 2, 3}
A.difference(B) => {1, 2, 3}
B - A => {8, 6, 7}
B.difference(A) => {8, 6, 7}
Uma vez que nós já sabemos como estas operações trabalham, vamos focar em
conhecer os principais métodos exclusivos do tipo set, que possuem o objetivo de
manipular e realizar diferentes verificações com essa estrutura de dados. Existem outros
métodos, menos utilizados, que podem ser consultados diretamente na documentação
do Python (PSF, 2022).
90
>>> # Criação dos conjuntos A e B
... c1 = {1, 2, 3, 4, 5}
... c2 = {4, 5}
... c3 = {91, 92, 93}
...
... # Adiciona um elemento ao conjunto
... c1.add(6)
... print(c1)
...
... # Adiciona os elementos de uma sequência iterável
... c1.update([2, 4, 6, 8])
... print(c1)
...
... # Descarta um elemento do conjunto,
... c1.discard(8)
... print(c1)
... # Diferentemente do set.remove(), o discard não gera um erro
... # se o elmento a ser removido não existir
... c1.discard(99)
... print(c1)
...
... # Verifica se os conjuntos são disjuntos, ou seja,
... # se não possuem nenhum elemento em comum
... print(c1.isdisjoint(c2))
... print(c1.isdisjoint(c3))
...
... # Verifica se o conjunto é subconjunto de outro
... print(c1.issubset(c2))
... print(c2.issubset(c1))
...
... # Verifica se o conjunto contém outro conjunto (superset)
... print(c1.issuperset(c2))
... print(c2.issuperset(c1))
{1, 2, 3, 4, 5, 6}
{1, 2, 3, 4, 5, 6, 8}
{1, 2, 3, 4, 5, 6}
{1, 2, 3, 4, 5, 6}
False
True
False
True
True
False
91
alunos para os seguintes idiomas: inglês, espanhol e francês. Considere também que um
mesmo aluno pode estar matriculado em uma única turma ou em múltiplas turmas,
conforme as listagens abaixo:
TURMA ALUNOS
ING – Inglês Gabriel, Caio, Maria, Ana, Juliano, Flávia, Rubens e Bruna
ESP – Espanhol Caio, Artur, Beatriz, Carolina, Maria, Juliano, Bruna e Rui
FRA – Francês Pedro, Bruna, Paula, Tiago, Maria, Flávia, Rui, Carolina
2. Identificar os alunos que estão matriculados em pelo menos duas turmas para
oferecermos um desconto;
92
Se ao invés de listas utilizarmos conjuntos, podemos resolver o problema sem
o inconveniente dos nomes repetidos. Basta utilizarmos a operação de união de
conjuntos, em que o resultado será outro conjunto, com todos os alunos. Porém, o
conjunto resultante será sem repetições (pois esta é a definição de um conjunto).
Observe, pela saída do código abaixo, que agora temos uma relação dos nomes de todos
os alunos, sem repetições.
O problema 2 também pode ser resolvido utilizando o tipo set e suas operações.
Para tanto, precisamos primeiro descobrir quais são os alunos que estão,
simultaneamente, em cada par de turmas (ING e ESP), (ING e FRA) e (ESP e FRA). Ou
seja, precisamos calcular a interseção entre estes pares de conjuntos. Em seguida
podemos realizar a união destas interseções, gerando a lista final de alunos que estão
em pelo menos duas turmas. O código abaixo ajuda a entender essa lógica.
>>> ING = {'Gabriel', 'Caio', 'Maria', 'Ana', 'Juliano', 'Flávia', 'Rubens', 'Bruna'}
... ESP = {'Caio', 'Artur', 'Beatriz', 'Carolina', 'Maria', 'Juliano', 'Bruna', 'Rui'}
... FRA = {'Pedro', 'Bruna', 'Paula', 'Tiago', 'Maria', 'Flávia', 'Rui', 'Carolina'}
...
... # 1 – Interseção entre os pares de turmas: (ING & ESP), (ING & FRA) e (ESP & FRA)
... # 2 – Calcula a união das interseções
... ALUNOS_DESCONTO = (ING & ESP) | (ING & FRA) | (ESP & FRA)
...
... # Exibição do resultado
... print('Relação de dos alunos com desconto:')
... print(ALUNOS_DESCONTO)
93
Relação de todos os alunos da escola:
{'Rui', 'Juliano', 'Bruna', 'Flávia', 'Maria', 'Carolina', 'Caio'}
>>> ING = {'Gabriel', 'Caio', 'Maria', 'Ana', 'Juliano', 'Flávia', 'Rubens', 'Bruna'}
... ESP = {'Caio', 'Artur', 'Beatriz', 'Carolina', 'Maria', 'Juliano', 'Bruna', 'Rui'}
... FRA = {'Pedro', 'Bruna', 'Paula', 'Tiago', 'Maria', 'Flávia', 'Rui', 'Carolina'}
...
... # 1 – Interseção entre os pares de turmas: (ING & ESP), (ING & FRA) e (ESP & FRA)
... # 2 – Calcula a união das interseções
... ALUNOS_DESCONTO = (ING & ESP) | (ING & FRA) | (ESP & FRA)
...
... # Exibição do resultado
... print('Relação de dos alunos com desconto:')
... print(ALUNOS_DESCONTO)
Dicionários
As outras estruturas de dados que vimos até o momento são formadas por
coleções de itens, ordenadas ou não. Em Python, um dicionário, que é do tipo de dados
dict, também é uma coleção de itens, entretanto cada elemento é um par key – value
(chave – valor). Estes pares indicam que cada elemento possuí um valor/value atrelado
à uma chave/key.
94
Nas listas, tuplas e strings, acessamos os elementos da sequência por meio de
um índice (posição). Nos dicionários isso ocorre de forma diferente, pois o acesso aos
valores (value) dos itens é realizado por meio de uma chave (key) que o identifica. O
nome dicionário é uma analogia aos dicionários da vida real, que mapeiam, para cada
termo (key) um significado (value). Dessa forma, em Python, os dicionários são
estruturas de dados que nos permitem mapear chaves à valores.
27
Como citado anteriormente, uma das vantagens da utilização das tupla em relação às listas é o fato
delas poderem ser utilizadas com chaves em dicionários, uma vez que são imutáveis.
95
O acesso aos elementos é realizado de forma semelhante às listas e tuplas, por
meio do operador de acesso com colchetes ([ ]). Mas ao invés de indicarmos o índice do
elemento, indicaremos a chave do elemento desejado.
zero
dois
Meu nome é Antônio e tenho 36 anos
KeyError: 'endereço'
None
Os dicionários são tipos mutáveis e por isso podemos adicionar novos itens ou
alterar o valor dos itens atuais, utilizando também o operador [ ]. Se a chave indicada já
96
estiver presente na estrutura, o valor mapeado para esta chave será atualizado. No caso
de não estar presente, um novo par (key: value) será adicionado ao dicionário.
{'nome': 'Antônio Carlos', 'idade': 36, 'sexo': 'masculino', 'endereço': 'Rua 123'}
Assim como todas as outras estruturas de dados, o tipo dict também possuí
operadores, funções e métodos que operam seus elementos. Enquanto algumas destas
operações se comportam da mesma forma que nas demais estruturas, outras possuem
pequenas diferenças:
97
... d1 = {'zero': 0, 'um': 1, 'dois': 2, 'três': 3, 'quatro': 4}
... print(d1)
...
... # Encontra a maior e menor chave
... print('Maior e menor chave:', max(d1), min(d1))
...
... # Adiciona elementos de um outro dicionario
... d1.update({'cinco': 5, 'seis': 6})
... print(d1)
...
... # Verifica se o dicionário possui as seguintes chaves
... print("A chave 'dois' está no dicionário?", 'dois' in d1)
... print("A chave 'cinco' não está no dicionário?", 'dois' in d1)
...
... # Remove o elemento com chave 'zero'
... d1.pop('zero')
... print(d1)
98
... if key == 'dez':
... print('Chave quatro encontrada!')
...
... # Itera sobre os valores
... soma = 0
... for value in d1.values():
... soma = soma + value
... print('Soma dos valores do dicionário:', soma)
...
... # Itera sobre os itens
... for key, value in d1.items():
... print(key, value)
...
zero 0
um 1
dois 2
três 3
quatro 4
99
Capítulo 9. Funções em Python
100
Apesar de estarem sendo introduzidas agora no curso, nós já utilizamos funções
diversas vezes nos capítulos anteriores, como por exemplo a função print(), para
exibição de mensagens, a função range(), que gera uma sequência de inteiros, e a função
len(), que retorna o tamanho de uma sequência. Entretanto, neste capítulo serão
discutidos os aspectos fundamentais das funções, assim como a sua criação e utilização.
Declaração de Funções
101
• O <bloco de código>, que irá compor o corpo da função, é o conjunto de
instruções responsável por realizar as computações que a função irá
desempenhar.
• Por fim, uma instrução de retorno (return), que é responsável por retornar o
resultado da função. Uma vez que existem funções que não retornam valores,
sua declaração é opcional.
Observe que para cada lista utilizamos o mesmo trecho de código para
computar a sua soma, variando apenas as variáveis envolvidas na computação. Imagine
102
agora se a mesma tarefa fosse necessária para computar a soma de mil listas? Nós
teríamos que escrever o mesmo bloco de código mil vezes! É justamente este retrabalho
que as funções evitam. Desta forma, podemos reescrever o mesmo código utilizando
funções:
Utilização de Funções
103
... boas_vindas('Priscila')
... print(area_triangulo(4, 5))
...
... boas_vindas('Maria')
... boas_vindas('Joana')
...
... print(area_quadrado(4))
... print(area_quadrado(10))
...
... boas_vindas('Antônio')
... print(area_quadrado(10))
...
... print(area_triangulo(5, 2))
... print(area_triangulo(4, 5))
>>> # Realiza uma divisão. Se o divisor é zero, retorna uma mensagem de erro.
... def div(dividendo, divisor):
... if divisor == 0:
104
... print('ERRO: Divisor igual à zero!')
... return
... return dividendo / divisor
...
... # Função similar à função div, mas que retorna o dividendo e o resto da divisão.
... def div_qr(dividendo, divisor):
... if divisor == 0:
... print('ERRO: Divisor igual à zero!')
... return
... quociente = dividendo // divisor
... resto = dividendo % divisor
... return (quociente, resto)
...
... print('div(10, 4) ==>', div(10, 4)) # dividento=10 e divisor=4
... print('div_qr(10, 4) ==>', div_qr(10, 4)) # dividento=10 e divisor=4
... print('div(10, 0) ==>', div(10, 0)) # dividento=10 e divisor=0
Observe que mesmo sem retornar um valor, o comando return pode ser
utilizado para abortar a execução da função, semelhante ao comando break das
instruções de repetição.
105
>>> print('div(10, 0) ==>', div(10, 0)) # dividento=10 e divisor=0
>>> # atribuição dos múltiplos valores em uma variável única do tipo tupla
... resultado = div_qr(21, 5)
... print('resultado:', resultado, type(resultado))
...
... # atribuição dos múltiplos valores em variáveis separadas
... quociente, resto = div_qr(21, 5)
... print('quociente:', quociente, type(quociente))
... print('resto:', resto, type(resto))
Para finalizar a análise das funções div e div_qr, observe que as duas possuem
um trecho de código em comum:
if divisor == 0:
print('ERRO: Divisor igual à zero!')
return
Se o objetivo das funções é reaproveitar código, por que não transformar estes
trechos repetidos em uma nova função? Desta forma, pode-se ter funções utilizando
outras funções:
106
return True
return False
Nas seções anteriores aprendemos como criar uma função e como utilizá-la.
Vimos também a passagem de valores para as funções são realizadas por meio de
argumentos. Iremos agora conhecer algumas particularidades sobre os tipos de
argumentos que o Python suporta. Para tanto, antes consideremos a seguinte função:
25
Essa função possuí dois argumentos e a utilizamos com dois valores (5 e 10).
Desta forma, como passamos o número exato de argumentos, ela executou
normalmente, sem erros.
107
Seria possível também passar os valores dos argumentos em uma ordem
diferente, mas neste caso precisamos declarar o nome dos argumentos na chamada da
função, conforme o exemplo a seguir.
25
Esse conceito permite que os argumentos de uma função possam ter um valor
default. Podemos atribuir um valor padrão para um argumento por meio do operador
de atribuição (=), conforme o exemplo a seguir.
108
>>> def exibe_pessoa(nome, idade=30):
... print(f'Meu nome é {nome} e tenho {idade} anos.')
...
... exibe_pessoa('Antônio')
... exibe_pessoa('Antônio', 36)
Observem que definimos uma função com dois argumentos (nome e idade), e
definimos um valor padrão para o segundo argumento (idade=30). Desta forma,
podemos utilizar a função passando apenas o argumento obrigatório (nome), como na
primeira chamada da função. Neste caso, será atribuído o valor padrão (30) ao valor do
argumento idade. Ou podemos utilizar a função com os dois argumentos definidos,
como foi o caso da segunda chamada.
109
Capítulo 10. Módulos
110
cada tipo de cálculo geométrico (área, volume, perímetro etc.). A organização e a divisão
dos códigos em módulos dependerão do seu objetivo com o programa. O importante é
ter em mente que a criação dos módulos é essencial para a modularização dos
programas, principalmente aqueles com milhares de linhas de código.
Por exemplo, vamos criar um módulo, chamado areas que contém funções
básicas para o cálculo da área de diferentes figuras geométricas. Para tanto, primeiro
precisamos criar um arquivo e em seguida salvá-lo com o nome areas.py. Em seguida,
basta adicionarmos o conteúdo do módulo, que são as funções que irão realizar os
cálculos:
# Define o valor de PI
PI = 3.141592
Voila! Já temos o nosso primeiro módulo e agora basta utilizarmos ele para
calcular as áreas de nossas figuras geométricas. Em Python, a utilização de códigos
externos é realizada por meio da importação de módulos, com a sintaxe: import
<modulo>. Portanto, para importamos o nosso módulo de exemplos, devemos utilizar a
instrução:
111
>>> import areas
20.0
20.0
>>> quadrado(6)
36
>>> PI
3.141592
112
e dentro destes módulos as funções são nomeadas de acordo com as figuras (da mesma
forma que fizemos no arquivo areas.py). Se fizermos a importação direta das funções
dos dois módulos, perderemos a referência de qual função faz parte de cada módulo.
20.0
>>> ar.quadrado(6)
36
[('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D')]
28
A lista completa de todos os módulos embutidos pode ser encontrada na documentação oficial do
Python (PSF, 2022): https://docs.python.org/3/py-modindex.html
113
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
Além dos módulos embutidos do Python, existem diversos outros módulos que
são desenvolvidos e mantidos por terceiros. Até você pode criar o seu próprio módulo
e em seguida disponibilizá-lo para que os outros desenvolvedores possam utilizá-lo. O
módulo, ou um conjunto deles, pode ser disponibilizado na forma de packages29,
"empacotando" os códigos em um arquivo e em seguida fazendo o upload para algum
repositório de bibliotecas em Python.
29
Tutorial oficial com um guia sobre o empacotamento de códigos em Python:
https://packaging.python.org/en/latest/tutorials/packaging-projects/
30
Repositório oficial de pacotes Python: https://pypi.org/
114
desenvolvimento de uma aplicação do mundo real e dependendo do tipo desta
aplicação, não iremos utilizar uma média de 10 a 30 pacotes que precisarão ser
instalados destes repositórios oficiais.
No curso estamos utilizando o Google Colab e ele já possui vários pacotes extras
instalados por padrão. Entretanto, se você estiver utilizando o Python instalado em seu
computador ou se estiver escrevendo uma aplicação real, muito provavelmente você
precisará instalar pacotes extras no seu ambiente Python.
Também é possível atualizar um pacote para a sua versão mais atual, utilizando
o pip:
31
Página oficial do pacote pandas: https://pandas.pydata.org/
115
É importante ressaltar que o pip é um programa a parte do Python. Ou seja,
este comando deve ser executado no seu terminal de comandos e não dentro de uma
execução interativa do Python. Geralmente, as instalações padrões do Python já trazem
consigo o pip instalado, entretanto se for necessário instalar o pip, basta seguir o
tutorial32 de instalação dele.
Por fim, se for necessário instalar um pacote no Google Colab, podemos fazer
uma chamada de comando do sistema direto das células dele. Para isso, basta
indicarmos que o comando é do sistema com um ponto de exclamação no início:
Collecting igpu
Downloading igpu-0.1.2-py3-none-any.whl (15 kB)
Collecting pynvml
Downloading pynvml-11.4.1-py3-none-any.whl (46 kB)
|████████████████████████████████| 46 kB 1.7 MB/s
Requirement already satisfied: psutil in /usr/local/lib/python3.7/dist-packages (from igpu) (5.4.8)
Installing collected packages: pynvml, igpu
Successfully installed igpu-0.1.2 pynvml-11.4.1
32
Tutorial de instalação pip: https://pip.pypa.io/en/stable/installation/
116
Capítulo 11. Manipulação de Arquivos
Existem diferentes formatos de arquivos como CSV, JSON, XML, YML e vários
outros. Para cada um destes formatos o ideal é utilizar um pacote Python desenvolvido
especificamente para a manipulação de seus dados. Entretanto, todos esses pacotes,
muito provavelmente, devem utilizar os conceitos básicos de manipulação de arquivos
que iremos apresentar a seguir.
117
Criação, Abertura e Fechamento de Arquivos
MODO DESCRIÇÃO
'r' Modo somente leitura (modo padrão).
Modo de escrita. Cria um arquivo, caso ainda não exista, ou substitui o
'w'
arquivo atual.
Modo de escrita. Cria um arquivo e, se o arquivo já existir, retorna um
'x'
erro.
Modo de escrita. Cria um arquivo, caso ainda não exista. Se o arquivo já
'a'
existir, novas escritas serão adicionadas ao final dele.
't' Abre o arquivo no modo texto (modo padrão).
'b' Abre o arquivo no modo binário.
118
arquivo_valores.close()
Leitura de Arquivos
A seguir, será utilizado como exemplo um arquivo contendo dados das maiores
cidades do Brasil. Cada linha conterá os dados de uma cidade, no seguinte formato:
33
Dados extraídos de: https://exame.com/brasil/as-200-cidades-mais-populosas-do-brasil/
119
Existem três maneiras simples de lermos os dados de um arquivo. A primeira é
a leitura de todas as linhas do arquivo, de uma única vez, e armazenando o conteúdo
em uma variável do tipo string. Para tanto, utiliza-se o método read():
Outra maneira é a leitura das linhas do arquivo por meio do método readlines().
Este método retorna uma lista de strings, onde cada elemento da lista corresponde à
uma linha do arquivo:
['SP; São Paulo; 11895893\n', 'RJ; Rio de Janeiro; 6453682\n', 'BA; Salvador; 2902927\n', 'DF; Brasília; 2852372\n', 'CE; Fortaleza;
2571896\n', 'MG; Belo Horizonte; 2491109\n', 'AM; Manaus; 2020301\n', 'PR; Curitiba; 1864416\n', 'PE; Recife; 1608488\n', 'RS;
Porto Alegre; 1472482\n', 'PA; Belém; 1432844\n', 'GO; Goiânia; 1412364\n', 'SP; Guarulhos; 1312197\n', 'SP; Campinas;
1154617\n', 'MA; São Luís; 1064197']
Observe que este método inclui a quebra de linha ('\n') para cada item da lista,
sendo necessário o tratamento posterior para removê-las. Por exemplo, pode-se criar
outra lista (novas_linhas) onde, para cada elemento da lista anterior, fosse aplicado o
método rstrip()34:
34
Como visto no Capítulo 3, o método rstrip() remove caracteres em branco e quebras de linha ao final
de uma string.
120
>>> novas_linhas = []
... for linha in linhas:
... novas_linhas.append(linha.rstrip())
... print(novas_linhas)
['SP; São Paulo; 11895893', 'RJ; Rio de Janeiro; 6453682', 'BA; Salvador; 2902927', 'DF; Brasília; 2852372', 'CE; Fortaleza;
2571896', 'MG; Belo Horizonte; 2491109', 'AM; Manaus; 2020301', 'PR; Curitiba; 1864416', 'PE; Recife; 1608488', 'RS; Porto
Alegre; 1472482', 'PA; Belém; 1432844', 'GO; Goiânia; 1412364', 'SP; Guarulhos; 1312197', 'SP; Campinas; 1154617', 'MA; São
Luís; 1064197']
Por fim, a última maneira é iterar sobre as linhas do arquivo, da seguinte forma:
Escrita de Arquivos
121
O segundo método, writelines(linhas), possibilita a escrita de diversos textos de
uma só vez, utilizando como parâmetro uma estrutura de dados que seja iterável (ex.:
list ou tuple). Por exemplo, o trecho abaixo adiciona as próximas quatro cidades da lista:
linhas = [
'AL; Maceió; 1005319\n',
'RJ; Duque de Caxias; 878402\n',
'RN; Natal; 862044\n',
'MS; Campo Grande; 843120\n'
]
arquivo = open('cidades.txt', 'a')
arquivo.writelines(linhas)
arquivo.close()
122
Capítulo 12. Recursos Úteis da Linguagem
Não poderíamos finalizar o nosso curso sem antes conhecer um pouco destes
recursos úteis que o Python oferece. Portanto, vamos conhecer alguns conceitos mais
complexos da linguagem, mas que serão possíveis de compreendermos com todo o
conhecimento que adquirimos até aqui. Desta forma poderemos deixar nossos códigos
mais pythonicos35 ainda.
Compreensão de Listas
35
A expressão código pythonico (derivado do inglês pythonic), apesar de ser vaga, é comumente utilizada
na comunidade de desenvolvedores Python para referenciar um código legível, limpo e que faz uso
frequente e correto dos recursos da linguagem. Apesar de não existir um guia oficial, muitos
desenvolvedores consideram que um código pythonico deve seguir as regras do PEP 20 (também
conhecido como The Zen of Python).
123
Este recurso é mais eficiente do que o modo tradicional de criação, pois requer
um uso menor de memória e a operação é realizada em menos tempo.
Ou seja, para cada item da sequencia iterável aplica uma transformação expr.
Por exemplo, tradicionalmente, para criar uma lista dos números de 1 a 10 elevado à
potência 2, seria utilizado o seguinte bloco de código:
>>> potencias = []
... for item in range(1, 11):
... potencias.append(item ** 2)
... print(potencias)
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150]
['A', 'N', 'T', 'O', 'N', 'I', 'O']
[True, False, True, False, True, False, True, False, True, False]
Considere agora que, também, deverá ser criado uma lista dos números de 1 a
10 elevado à potência 2. Entretanto, apenas os números ímpares devem ser
considerados e os números pares descartados. Ou seja, existe uma condição a ser
124
verificada (se o número é ímpar). Tradicionalmente, pode-se resolver este problema
com o seguinte trecho de código:
>>> potencias = []
... for item in range(1, 11):
... if item % 2 != 0:
... potencias.append(item ** 2)
print(potencias)
Compreensão de Dicionários
125
Observe que é utilizada chaves ({ }) ao invés de colchetes ([ ]), por serem o
símbolo de definição dos dicionários em Python.
Todos numeros: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
Números ímpares: {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
Todos numeros: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}
Números ímpares: {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
126
Funções Anônimas (Funções Lambda)
Uma função anônima em Python é uma função definida sem nome (por isso o
termo anônimo). Enquanto as funções tradicionais são definidas utilizando a palavra-
chave def, as funções anônimas são definidas usando a palavra-chave lambda. Portanto,
este tipo de função é conhecido popularmente como funções lambda. Estas funções
possuem a seguinte sintaxe:
Uma particularidade destas funções é que elas podem ter qualquer número de
argumentos, mas podem terá apenas uma expressão. Desta forma, a expressão será
computada e o seu resultado será retornado. Por isso, nas funções lambdas não é
necessário declarar a palavra-chave return.
16
127
<class 'function'>
As funções lambda são úteis quando precisamos de uma função específica por
um curto período. Geralmente utilizamos estas funções em conjunto com outras
funções que possuem como argumento outra função, como por exemplo a função
map(), que permite que apliquemos uma função em todos os elementos de uma lista,
como no exemplo a seguir.
Considere um código que cria uma variável, chamada var, e atribui a ela um
valor de acordo com uma das seguintes condições: Se o nome do programador tiver
mais de 5 letras, o valor de var deverá ser 100. Caso contrário (o nome tem 5 ou menos
letras), o valor de var deverá ser 0.
128
100
100
Este recurso faz com que seja possível transformar quatro linhas de código em
apenas uma. Outro recurso pythonico!
129
Referências
BRITO, M. Python F-String: 73 Examples to Help You Master It. miguendes's blog, 2020.
Disponível em: <https://miguendes.me/73-examples-to-help-you-master-pythons-f-
strings>. Acesso em: 6 março 2022.
CORMEN, T. et al. Algoritmos: Teoria e Prática. 2. ed. [S.l.]: LTC, 2012. 944 p. ISBN
8535236996.
MARVIN, R.; NG’ANG’A, M.; OMONDI, A. Python Fundamentals. [S.l.]: Packt Publishing
Ltd, 2018. 324 p. ISBN 1789807328.
PAREWA LABS PVT. LTD. Python Sets. Programiz, 2022. Disponível em:
<https://www.programiz.com/python-programming/set>. Acesso em: 6 março 2022.
130
PILGRIM, M. Dive Into Python 3. 2. ed. [S.l.]: Apress, 2009. 360 p. ISBN 1430224150.
PSF. Documentação Python 3.9.10. Documentação Python 3.9.10, 2022. Disponível em:
<https://docs.python.org/pt-br/3.9/index.html>. Acesso em: 6 Março 2022.
REAL PYTHON. Python 3 Installation & Setup Guide. Real Python, 2020. Disponível em:
<https://realpython.com/installing-python>. Acesso em: 7 março 2022.
SLATKIN, B. Python Eficaz. 1. ed. São Paulo: Novatec, 2016. 296 p. ISBN 978-85-7522-
510-3.
131
TIOBE. The Python Programming Language. TIOBE Index, 2022. Disponível em:
<https://www.tiobe.com/tiobe-index/python/>. Acesso em: 8 Fevereiro 2022.
VANDERPLAS, J. A Whirlwind Tour of Python. 1. ed. [S.l.]: O'Reilly Media, Inc., 2016.
ISBN 9781491964644.
132