1. Introdução

No Módulo 2 do curso, você aprendeu especialmente sobre as variáveis string, com operações simples, realizadas dentro do console. Neste módulo, passaremos ao espaço em que você efetivamente desenvolverá seus programas: o Editor.

Somente nesse espaço é que você conseguirá criar algoritmos: sequências de comandos, que devidamente executados, podem oferecer os resultados que você busca por meio desse encadeamento de funções e variáveis.

2. Do Console ao Editor

O Editor é a parte mais importante do Spyder, tanto que ele fica no ponto que mais se destaca ao nosso olhar: o canto superior direito. No primeiro momento, o Spyder apresenta no Editor uma propaganda do Kite, que é uma ferramenta que auxilia o desenvolvimento de softwares.

Trata-se de uma ferramenta interessante, que oferece um auto-completar mais robusto, mas que escapa aos objetivos deste curso (se você tiver interesse, existe nessa tela o link para o help desse aplicativo). Então, nosso primeiro passo será fechar as duas janelas que estão em aberto (temp.py e kite_tutorial.py) e abrir um novo arquivo, para conter o seu programa.

Fechando as duas janelas, o Spyder abre automaticamente um documento novo: untitled.py. Esse é um documento em branco, apenas com uma indicação da autoria e da data de criação (em verde, entre aspas triplas) e um comentário na primeira linha indicando que o encoding padrão é UTF-8.

Encoding indica a forma como os dados são gravados. Quando você grava um arquivo, cada caractere é representado por um código. Um encoding é um conjunto específico desses códigos que designam um caractere específico. Se você grava um arquivo com um encoding, é preciso abri-lo com o mesmo encoding, sob pena de haver leituras erradas.  No nosso caso, devemos usar exatamente o UTF-8, que é o encoding padrão da internet, utilizado inclusive nas páginas dos tribunais brasileiros.

Comentários são trechos de código introduzidos por um #, que indica que essa parte do texto não deve ser executada. Usamos os comentários para o que se chama de documentação, que é a explicação do que faz cada parte do nosso programa, para facilitar a sua compreensão posterior (inclusive por nós mesmos, já que com o tempo nos esquecemos do sentido específico de cada uma das linhas que escrevemos).

Se você quiser, pode alterar esse texto incial dos seus códigos no menu Tools: Prefereces: Editor: Advanced Settings: Edit Template for new files. Isso abrirá o arquivo template.py, que em que você pode definir o que você quer que apareça no início de cada um dos seus programas.

No menu Tools: Preferences: General: Advanced Settings você também pode alterar a linguagem do Spyder para português, se você preferir. Mas vamos continuar usando o inglês, pois a maior parte dos recursos de auxílio à programação está em inglês e, por isso, dominar a terminologia em inglês facilita o seu desenvolvimento posterior.

Agora que você tem o seu Editor aberto, podemos fazer nosso primeiro exercício: retome o ponto 4.4 do texto Funções e Variáveis, em que criamos um mecanismo para extrair o nome do relator de uma string. Como usamos o console, você precisou fazer cada passo. Agora, o desafio é criar uma sequência de passos a serem seguidos de uma vez, para alcançar o resultado.

Uma das formas de resolver esse problema (e sempre há vários caminhos!) é o seguinte algoritmo:

# atribui um conteúdo à variável dados
dados = 'ADI 333, Relator: Marco Aurélio, Resultado: Procedente'

# define o ponto a partir do qual você pretende extrair os dados.
inicio = dados.find('Relator: ') + len('Relator: ') 

# define o ponto até o qual você extrairá os dados
fim = dados.find(',' , inicio)

# atribui à variável relator a extração dos dados 
# entre o marcador de início e o de fim
relator = dados[inicio:fim]

print (relator)
IteradoresListas1.py

Essa sequência de passos determinados é o que chamamos de algoritmo, e o código acima determina um algoritmo que, uma vez executado, extrairá da variável string dados a informação relator, e imprimirá o seu conteúdo na tela.

Note que a caixa acima não é mais uma captura de tela do console. Trata-se de uma caixa de código, cuja grande vantagem é a de conter um texto que pode ser copiado. Basta você selecionar o texto com o mouse, copiar e depois colar no Spyder. Note que a numeração das linhas é um elemento de formatação e que, por isso, esses números não são copiados juntamente com o conteúdo do código.

Esse trecho de código pode ser colado no console e, se você clicar no enter, vai executar o programa e gerar o output Marco Aurélio. Porém, nossa indicação é que você cole o texto no editor, para poder trabalhar facilmente sobre ele.

Se você colar esse pequeno programa no seu Editor, não ocorrerá nada imediatamente. No console, os textos são executados meio de um Enter. No Editor, para executar o programa, é preciso utilizar o comando Run (cujo atalho é F5), o que vai fazer com apareça no console o resultado do input do seu programa: o output Marco Aurélio.

A grande vantagem do Editor é que, ao contrário do que ocorre no Console, você pode gravar os códigos que você desenvolve, (utilizando o Save File, cujo atalho é Ctrl-S), o que gera arquivos com a extensão .py. Tais arquivos podem ser depois abertos e executados no ambiente do Spyder, mas também podem ser executados diretamente pelo seu sistema operacional.

3. Listas

Agora é hora de inserir um novo tipo de variável, que também usaremos exaustivamentes: as listas. Enquanto as strings são sequências de caracteres, as listas são sequências de objetos.

animais 		= ['cachorro', 'bem-te-vi', 'jacaré']
numeros 		= [1, 2, 3, 100, 2165]
listas 			= [animais, numeros]
tudomisturado 	= [1, 2, 'cachorro', numeros]

Uma das coisas interessantes do Python é que não importa o que você coloca em uma lista. Tudo cabe nelas e cada um desses objetos é identificado pela sua posição, exatamente como nas strings. As únicas peculiaridades das listas são bastante intuitivas:

  1. elas ocorrem sempre entre colchetes. Se você usar parênteses, o que  terá será uma lista imutável (que não pode ter sua composição alterada por funções), que se chama tupla.
  2. os objetos são separados por vírgulas.

Com o que você já sabe de posição nas strings, você pode compreender as expressões abaixo. Caso não entenda, convém voltar ao texto do Módulo 2 e reler o texto sobre posição nas strings).

Não é demais lembrar que a primeira posição é a 0 e não a 1.

Você pode ler elementos de uma lista usando a mesma lógica das strings, com os marcadores de posição (index). Mas como você pode fazer para ler o último valor de uma lista?

Primeiro, vamos construir uma lista com os números inteiros de 0 a 9, o que podemos fazer aplicando a função list ao comando range(10), que você já conhece.

Para extrair o último elemento da lista, usaremos posições negativas. Até agora, somente trabalhamos com posições positivas, mas também podemos usar posições negativas, baseadas no fato de que o Python trata a última posição como sendo também a primeira posição negativa: -1. Assim, se você quiser somente os dois últimos números de uma lista com 10 números, você pode usar o comando:

lista = list(range(10))
print(lista[-2:])

Outra característica interessante das listas é que elas são concatenáveis, como as strings. Veja o resultado do código:

lista = list(range(10))
print (lista + lista)

Uma vez que você entenda como funciona uma lista, você entenderá facilmente o que é um iterador, pois o iterador que utilizamos (for) é normalmente baseado em listas.

4. Iterador for

O iterador for é uma forma de executar uma função com relação a cada um dos objetos de uma lista. Por exemplo:

for item in animais:
	print (item)

Se você acrescentar essas duas linhas ao seu editor e executar (run), o resultado será:

Portanto, o que o comando anterior realizou foi:

  1. processar a função print uma vez para cada uma das posições contidas na lista animais;
  2. em cada execução da função, atribuir à variável item o valor correspondente ao objeto contido na lista.

Como a lista tem 3 itens, são 3 execuções de print, cada uma imprimindo o valor contido na respectiva posição.

No âmbito do direito, podemos ter uma lista composta pelos numeros das adis a serem buscadas e uma string com o formato geral dos endereços em que eles estão gravados, como já vimos no texto Funções e Variáveis. Se usarmos o iterador for, podemos gerar os endereços que devem ser buscados no STF.

adi = ('333','444', '555', '666')
url = 'http://www.stf.jus.br/portal/peticaoInicial/verPeticaoInicial.asp?base=ADI&documento=&s1=0&numProcesso='

for item in adi:
    print (url + item)

Se você observar com cuidado, verá que o formato geral do for é:

for variável in lista:
   função a ser repetida

Dois detalhes importantes sobre esse formato:

  1. É essencial que a primeira linha seja encerrada por um ':', que indica que depois disso virá a função a ser repetida.
  2. É necessário um marcador para que o Python saiba exatamente qual é a função a ser iterada. Há linguagens que marcam com parênteses ou com chaves essa funções. Em Python não: a única marcação exigida é um recuo, que chamamos tipicamente de indentação (um anglicismo que vem de indentation, palavra inglesa para recuo).

Não importa quantos espaços você coloque antes do print, desde que haja um espaço que o deixe mais à direita que o for. Porém, há um costume entre os desenvolvedores em Python de deixar 4 espaços, que é o recuo padrão, ou usar um símbolo de tabulação.

Parece que dois espaços é pouco, pois pode dar destaque suficiente na leitura, mas isso é só uma questão de legibilidade. Se você colocar 1, 2 ou 10 espaços, seu programa rodará da mesma forma. Porém, uma vez que você definir uma indentação, o Python só vai entender como ligado ao for outras linhas de comando que tenham o mesmo recuo.

Inclusive, se você usar uma indentação de 1 tabulação e outra de 4 espaços, elas não serão entendidas como recuos idênticos. Uma vez que você defina o recuo usado na linha seguinte ao for, ele precisa ser mantido, para que o Python entenda que funções nas linhas seguintes fazem parte do loop (código a ser iterado) estabelecido pelo for.
for item in adi:
    print ('endereço da ADI' + item + ':')
    print (url + item)

Outro detalhe: não importa o nome que você dá à variável iterada. Usamos aqui o nome item, mas podemos usar n, vez, abacate ou qualquer outro nome válido para variáveis (tópico que também estudamos no texto passado). As expressões seguintes vão gerar exatamente o mesmo output do comando anterior.

for n in adi:
    print ('endereço da ADI' + n + ':')
    print (url + n)
    
for vez in adi:
    print ('endereço da ADI' + vez + ':')
    print (url + vez)

Atente a dois erros muito comuns que cometemos ao definir iteradores:

  1. Esquecer os dois pontos. Várias vezes eu esqueço e o resultado é um erro de invalid syntax, pois os ':' são necessários para a devida construção do iterador.
  2. Usar recuos diferentes, o que tipicamente gera como resultado um IndentationError.

Tomados esses cuidados básicos, você conseguirá dominar facilmente esse instrumento muito poderoso de iteração.

Desafio: tente descobrir qual é a interessante coincidência que ocorrerá quando você usa um for iterando a lista:

lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

for n in lista:
    print (n)

Trata-se de um caso bem particular, em que o valor do objeto contido na lista é idêntico a sua posição. O número 0 ocupa a posição 0, o número 1 ocupa a posição 1 e assim por diante. Por isso, a iteração acima vai gerar um curioso resultado:

Essa é uma  ferramenta importante para nós porque se trata de uma forma simples de gerar uma lista ordenada de números inteiros, que se inicia em 0 (como as posições de sequências em Python).

E se eu quisesse uma lista de 1000 números? Não seria aconselhável escrever uma lista assim, mas você pode gerá-las trocando a sua lista escrita a mão pela expressão range(1000):

for n in range(1000):
    print (n)

Em menos de um segundo, seu computador deve ser capaz de imprimir esses 1000 números na tela. No meu, ele demorou algo em torno de 2 segundos para produzir uma sequência de 10.000 números.

Desafio: agora que você consegue produzir listas quase infinitas de números, você pode fazer algo muito útil para os nossos extratores: gerar listas com os endereços de todas as ADIs em um determinado intervalo: entre 5000 e 6000, por exemplo.
for n in range(1001):
    print ('ADI'+str(5000+n))

Repare neste código dois detalhes dos quais já havíamos falado antes:

  1. O intervalo entre a ação 5000 e a 6000 tem 1001 objetos;
  2. Só podemos concatenar strings com outras strings, nunca strings com números. Por isso, como você já vez na Atividade 1, é preciso converter a variável numérica n em uma string, o que se consegue pelo comando str(n). No caso, str(5000+n) porque 5.000 é o número inicial de nossa sequência.

A esta altura, você já deve ter imaginado que o problema que colocaremos no final desta unidade seja produzir a lista das urls que deverão ser buscadas para podermos colher as informações sobre esses processos. E você imaginou bem.

5. Combinando listas e iteradores

No último código, você aprendeu a gerar uma sequência de nomes de ADIs. Mas como é possível armazená-las em uma lista?

Basta usar, no lugar do print (que envia para a tela) o comando nomedalista.append, que armazena os dados na última posição de uma lista anteriormente definida.

Esse anteriormente definida é importante porque, antes de acrescentar elementos a uma lista, ela precisa ser criada, mesmo que esteja em branco, como ocorre no seguinte caso:

adi = []
for n in range(101):
    adi.append ('ADI'+str(5000+n))
    
print (adi)

Com esse código, você consegue gerar uma lista com os nomes de todas as ADIs de 500 a 5100. Essa é uma construção importante porque é com base em um comando deste tipo que podemos buscar os dados de cada processo contido em uma lista.

6. Expressões condicionais

Para construir programas mais complexos, é preciso construir expressões condicionais, que criem diferentes caminhos no seu algoritmo, para diferentes valores.

Se você pretende construir uma base de dados sobre as ADIs, você precisa ser capaz de construir comandos que determinem que uma informação seja inserida na sua base de dados, se e somente se, o campo classe tiver o valor 'ADI'.

Para criar algoritmos capazes de selecionar os andamentos mais relevantes de um processo, você precisa desenvolver comandos capazes de ignorar certos, se eles fizerem parte de uma lista que você definiu de andamentos irrelevantes para a sua pesquisa.

As expressões condicionais mais básicas seguem a estrutura:

  1. Se determinada afirmação for verdadeira, então realize tal sequência de comandos.

Mas como podemos perguntar se uma afirmação é verdadeira? Isso nos coloca frente ao conceito de variáveis booleanas.

6.1 Variáveis booleanas

Existem duas variáveis booleanas:

  1. True
  2. False

Elas vêm assim, escritas com inicial maiúscula, e elas são expressões reservadas (keywords) do Python, motivo pelo qual você nunca pode usar True ou False como nome de uma variável ou de uma função. A compreensão dessas variáveis é um dos elementos mais filosóficos da teoria computacional e, de fato, a própria concepção desse tipo de variável foi um dos conceitos fundamentais desenvolvidos no século XIX, que permitiram o desenvolvimento da filosofia da linguagem no século XX.

Tudo começa com uma pergunta linguística:

  • a que se refere o numeral '1'?

Como todo nome, o numeral um se refere a um determinado objeto. Nesse caso, o objeto referido é o número '1', que é uma certa quantidade. Já ressaltamos antes que não devemos confundir o nome do número, sejam eles numerais expressos em algarismos('1', 'i'), sejam eles expressos em letras ('um', 'one', 'uno'), sejam eles expressos por polinômios que apresentam operações matemáticas ('0,5 + 0,5', '0,24 * 4' ou '10/10'). O referente de todos esses nomes é o mesmo: a quantidade 1.

A mesma coisa ocorre com outros nomes: Napoleão Bonaparte se refere a uma pessoa determinada, buritirana se refere a um tipo de vegetal, açaí se refere a um tipo de fruta.

Mas a que se referem as frases, tais como:

  1. 2 + 2 = 4
  2. A terra gira em torno do sol.
  3. int('1') = 1

Se os termos das frases têm referentes concretos muito claros, é difícil saber qual é o referente da frase como um todo. Uma solução possível seria dizer: frases não têm referentes, o que é uma possibilidade razoável. Frases (diferentemente dos termos que a compõem) são enunciados que aparentemente não apontam para nenhum objeto, para nenhuma classe, para nenhuma ação.

Essa é uma solução possível, mas não é uma solução adequada à linguagens de programação, em que toda expressão válida precisa apontar para um objeto. Mas para qual objeto podem apontar as frases? Uma solução engenhosa foi proposta pelo matemático George Boole no século XIX: todas as expressões verdadeiras têm o valor Verdadeiro, todas as expressões falsas têm um valor Falso.

Ocorre que, em várias linguagens, o valor é um objeto:

  1. O valor do numeral 1 é o valor numérico 1.
  2. O valor de uma string é o conjunto de caracteres previamente defindo.
  3. O valor de uma lista é o conjunto ordenado de objetos que ela contém.
  4. O valor de uma expressão que envolve o operador de identidade é sempre True ou False, que são os valores booleanos.

Essa curiosa relação pode ser vista quando digitamos no console certos nomes ou expressões, pois o console retorna o seu valor como output.

Teste ingressar expressões como essas no seu console e você verá que toda vez que você colocar uma expressão de igualdade que pode ser processada (por ter os seus termos todos definidos), o resultado será sempre True ou False.

Lembre-se de que é preciso usar o operador '==' (que expressa uma relação de igualdade), e não com a função '=' (que atribui valores a variáveis).

A compreensão das expressões acima como verdadeiras (ou falsas) é intuitiva. O que não é intuitivo é a veracidade das seguintes expressões:

Em Python, o valor de toda expressão verdadeira é o valor booleano True e o valor de toda expressão falsa é o valor booleano False. Por isso, quando igualamos duas expressões verdadeiras, teremos sempre o valor 'True', visto que o operador de igualdade não compara textos (que são evidentemente diversos), mas compara valores.

6.2 Condicionais + Booleanos

Feita essa passagem pelas variáveis booleanas, você pode entender que toda expressão condicional pode ser expressada em termos booleanos:

  • Se True, então execute a função f.

Em termos de código de Python, teremos algo como:

expressao = (1 + 1 == 2)

if expressao:
    print (expressao)

Observe que, no explorador de variáveis, o valor da variável expressao não é '1 + 1 = 2' (o que corresponderia a uma string), o valor da expressão matemática 1 + 1 = 2 é simplesmente True.

Portanto, o comando que demos foi o correspondente a:

if True:
    print (True)

Agora que você entendeu a lógica subjacente, pode operar bem essa estrutura, sem cair em armadilhas. Em especial, você quase nunca quer que o seu programa retorne True or False. O que você normalmente quer é que, se a expressão for verdadeira (ou seja, se o valor dela for True), um determinado comando deve ser executado.

Um modelo que usaremos muito (mas muito mesmo) é procurar se determinadas expressões estão dentro de uma string ou dentro dos elementos de uma lista, o que pode ser conseguido com o seguinte código:

processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']

if 'ADI5500' in processos:
    print('O processo procurado está na lista')

Como a expressão 'ADI5500' in processos é verdadeira, o comando print será executado e o texto definido aparecerá na sua tela.

Usando a lógica de iteração que você já deve ter entendido, também podemos verificar se nesta lista (ou em qualquer lista), aparece o termo 'ADI':

processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']

for item in processos:
    if 'ADI' in item:
        print('O processo é uma ADI')

Esse é um programa que funciona, mas que tem um resultado ambíguo, pois ele simplesmente imprime duas vezes o mesmo texto, sem deixar saber qual é o item.

Existem algumas formas de melhorarmos essa funcionalidade:

Concatenação
processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']

for item in processos:
    if 'ADI' in item:
        print('O processo ' + item + ' é uma ADI')

Esse já é um resultado mais interessante, pois diferencia quais são as ADIs.

Criar lista
processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']
adi = []

for item in processos:
    if 'ADI' in item:
        adi.append(item)
        
print (adi)

Agora você tem uma nova lista. São somente duas ADIs nesta lista em concreto, mas essa lógica pode permitir que você extraia todas as ADIs existentes em uma lista, para depois extrair os dados dela.

Essa combinação de iteradores com expressões condicionais pode gerar uma infinidade de soluções interessantes para os seus desafios com dados.

6.3 Operadores de igualdade e diferença

Trabalhamos até aqui apenas com o operador de igualdade '==', que retorna o valor True quando liga duas expressões que têm o mesmo valor, seja esse valor um número (no caso de expressões numéricas), seja esse valor uma variável booleana (no caso de expressões).

Um dos nossos erros mais comuns (e mais difíceis de superar) é nossa tendência a usar o '=' como operador de igualdade, em vez de usar o '=='. Muitas vezes digitamos rapidamente expressões condicionais e não nos atentamos que estamos usando equivocadamente o '=' no lugar do '=='.

Oposto ao operador de igualdade, é o operador de diferença, que em Python é representado pelo '!=', como mostra o quadro abaixo, que você pode construir no Console. Já os operadores maior que e menor que seguem o uso que você já conhece de matemática básica.

6.4 Operadores booleanos

Para criar expressões ainda mais complexas, você pode usar os chamados operadores lógicos, ou operadores booleanos, visto que eles entram justamente nas operações cujos resultados são justamente as variáveis True e False:

  • and
  • or
  • not

Você certamente conhece esses operadores das pesquisas de jurisprudência, nas quais utilizamos esse tipo de lógica com frequência. Podemos começar com uma busca de todos os processos que contém a expressão "princípio da proporcionalidade". Depois, queremos refinar essa pesquisa e usamos um operador and para indicar que queremos todos os processos que contém essa expressão e que também contém em sua classe a string 'ADI'.

Podemos refinar ainda mais as nossas buscas, acrescentando novos operadores and, que tornam mais restritas os critérios que tornam verdadeira a expressão que avaliamos por meio da função if.

Quando queremos ampliar as buscas, usamos o or, pois a nossa expressão será verdadeira tanto se a primeira condição se cumprir quanto se a segunda condição se cumprir. Queremos processos, por exemplo, dos relatores Gilmar Mendes ou Dias Toffoli ou Ricardo Lewandowski. Com isso, nossa busca retornará todos os resultados que tornam True alguma dessas condições.

O not é um operador interessante porque ele inverte a variável booleana buscada. Muitas vezes, queremos excluir de uma lista todos os processos que não têm uma característica. Você deve ser capaz de entender o que o seguinte código muda em relação ao código da janela anterior.

processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']
adi = []

for item in processos:
    if 'ADI' not in item:
        adi.append(item)
print (adi)

Nesse caso, geramos uma lista de todos os processos que não têm a string 'ADI', em vez de gerar uma lista dos processos que a têm.

6.5 Expressões condicionais com Else e Elif

A expressão condicional if pode ser complementada por dois comandos que tornam mais plásticas as nossas expressões condicionais, pois elas permitem executar funções diversas no caso de a condição inicial ser False e não True. Continuando o nosso penúltimo código, podemos colocar uma condição else:

processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']
adi = []
adpf = []
outros = []

for item in processos:
    if 'ADI' in item:
        adi.append(item)
    else:
        outros.append(item)
        
print ('Lista de ADIs: ' + str(adi))
print ('Lista de outros processos: ' + str(outros))	

Agora temos dois resultados simultâneos, e não apenas um, o que é muito útil quando queremos fazer uma triagem.

Repare que o else vem no mesmo recuo do if, para que ele seja entendido como parte da mesma expressão condicional. E, tal como if e os iteradores, o else vem sempre complementado por um ':', cuja ausência gera um erro de sintaxe.

Para refinar a nossa triagem, podemos usar um operador elif (que vem de else if): ele é como um novo if, operando apenas nos casos em que a primeira condição não se confirmou. Por isso, falamos de condicionais encadeadas.

processos = ['ADI500', 'ADI5500', 'ADPF250', 'MS3456']
adi = []
adpf = []
outros = []

for item in processos:
    if 'ADI' in item:
        adi.append(item)
    elif 'ADPF' in item: 
        adpf.append(item)
    else:
        outros.append(item)
        
print ('Lista de ADIs: ' + str(adi))
print ('Lista de ADPFs: ' + str(adpf))
print ('Lista de outros processos: ' + str(outros))

Você também pode aninhar condicionais, o que ocorre quando a função executada por um if é também uma função condicional. Mas deixaremos esse desafio para as Atividades práticas.

6. Resumo

Neste texto, você deve ter aprendido:

  1. A criar programas no editor e salvá-los.
  2. Trabalhar com listas, extraindo os valores de certas posições.
  3. Criar loops com o for, executando comandos de forma iterada.
  4. Utilizar o iterador for para gerar sequências de números inteiros.
  5. Construir expressões condicionais simples.
  6. Entender que os valores de expressões com '==' são variáveis booleanas (True ou False).
  7. Desenvolver expressões condicionais com if, else e elif.