1. Expressões condicionais com if

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.

2. 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.

3. 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.

4. 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.

5. 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.

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. Entender que os valores de expressões com '==' são variáveis booleanas (True ou False).
  2. Desenvolver expressões condicionais com if, else e elif.