A linguagem Python suporta os seguintes operadores para booleanos:
| Operador | Significado |
|---|---|
not |
negação unária |
and |
E condicional |
or |
OU condicional |
Os operadores and e or são operadores em curto-circuito, ou seja, o segundo
operando só é avaliado se o resultado não puder ser determinado com base apenas
no valor do primeiro operando. Confuso? Vamos ver alguns exemplos neste artigo.
Caso prefira ver em vídeo, clique no player abaixo. O artigo completo se encontra após o vídeo.
Visão geral #
and
#
Considere que estamos procurando em uma lista dados um determinado valor 'X'
e que queremos ter o índice desse valor. As listas em Python possuem um método
para isso, mas aqui o objetivo é entender o conceito, então vamos resolver com o
mais básico da linguagem. Em um primeiro momento, vamos considerar que o valor
procurado efetivamente está na lista:
dados = ['A', 'C', 'D', 'X', 'Z']
Uma forma simples é com um loop while:
indice = 0
while indice < len(dados) and dados[indice] != 'X':
indice += 1
print(indice)
3
Repare no código anterior que primeiro checamos se o índice é menor que o tamanho da lista e depois verificamos se a posição avaliada é diferente do valor desejado. Vamos ver o que ocorre se mudarmos a ordem da comparação:
indice = 0
while dados[indice] != 'X' and indice < len(dados):
indice += 1
print(indice)
3
Observe que, aparentemente, não há diferença. Mas o que irá ocorrer se a lista não possuir o valor procurado?
Vamos redefinir nossa lista sem o valor 'X':
dados = ['A', 'C', 'D', 'Z']
Vamos fazer novamente nosso loop verificando antes se o índice é menor que o tamanho da lista:
indice = 0
while indice < len(dados) and dados[indice] != 'X':
indice += 1
print(indice)
4
Obtivemos o valor 4 para indice pois toda a lista foi percorrida e não se
encontrou o valor desejado. Assim, todos os índices válidos foram percorridos e,
quando se verificou que a primeira comparação (primeiro operando de and) não
era válida, o loop foi interrompido. Repare que o índice 4 não faz sentido nessa
lista, pois o maior índice possível é 3 (lembre-se que sequências em Python
começam em índice zero).
Agora vamos ver o que ocorre trocando a ordem dos operandos:
indice = 0
while dados[indice] != 'X' and indice < len(dados):
indice += 1
print(indice)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-6-d88901ad107a> in <module>
1 indice = 0
----> 2 while dados[indice] != 'X' and indice < len(dados):
3 indice += 1
4 print(indice)
IndexError: list index out of range
Um erro ocorre pois, quando temos 4 sendo associado à indice, o primeiro
operando é dados[4] != 'X'. Como o índice 4 não é válido, temos um
IndexError. Observe que o Python não avaliou o segundo operando, que iria
impedir o erro, caracterizando o comportamento conhecido como
curto-circuito.
Esse comportamento pode ser utilizado, como vimos nesse exemplo, para evitar
possíveis erros na avaliação do segundo operando. Avaliar primeiro se o índice é
menor que o comprimento impede que ocorra IndexError.
Em que se baseia esse comportamento? Em lógica booleana
básica. O operador and, de
conjunção lógica, só pode
ter resultado True se ambos os operandos forem True. Assim, o primeiro
operando tendo valor False já é o suficiente para que o loop seja
interrompido. Caso tenha ficado confuso, dê uma olhada em
tabelas-verdade, inclusive já fiz
um pequeno programa Python para construção de tabelas-verdade que você pode
conferir aqui.
Para deixar completo o artigo, a tabela verdade para o operador and, gerada
pelo projeto Truth Table
Generator é a seguinte:
+--------------+--------------+-----------------------------+
| operando_1 | operando_2 | operando_1 and operando_2 |
|--------------+--------------+-----------------------------|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
+--------------+--------------+-----------------------------+
Observe que, apenas quando os dois operandos são True, o resultado será
True. Assim, se o primeiro operando for False não há necessidade de avaliar
o segundo. É esse o princípio por trás do comportamento de curto-circuito.
or
#
Vamos ver exemplos para o operador or. Para entender esses exemplos,
precisamos saber que o interpretador da linguagem considera como False os
seguintes casos:
print(bool(False)) # a própria palavra reservada False
print(bool(None)) # a palavra reservada None
print(bool(0)) # o inteiro 0 (zero)
print(bool("")) # uma string vazia
print(bool(())) # uma tupla vazia
print(bool([])) # uma lista vazia
print(bool({})) # um dicionário vazio
False
False
False
False
False
False
False
Caso queira uma visão mais histórica desse comportamento, recomendo ver a PEP
285, que implementou o tipo bool
na linguagem Python.
Vamos então considerar as duas situações seguintes:
apelido = ""
def funcao_executada():
return "Executou a função"
print(apelido or funcao_executada())
Executou a função
apelido = "Chico"
print(apelido or funcao_executada())
Chico
Novamente, os comportamentos derivam de lógida booleana. O operador or, de
disjunção lógica, só pode
ter resultado False se ambos os operandos forem False. Assim, o primeiro
operando tendo valor True já é o suficiente para que o loop seja interrompido.
Por isso, no segundo caso, onde apelido não é uma string vazia, seu valor
lógico é True e a função não é executada.
Para deixar completo o artigo, a tabela verdade para o operador or, gerada
pelo projeto Truth Table
Generator é a seguinte:
+--------------+--------------+----------------------------+
| operando_1 | operando_2 | operando_1 or operando_2 |
|--------------+--------------+----------------------------|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
+--------------+--------------+----------------------------+
Compare a tabela com o que foi escrito para entender o comportamento.
Resumo do comportamento #
| Operação | Resultado | Observações |
|---|---|---|
x or y |
Se x é False, então y, senão x |
y é executado apenas se x é False |
x and y |
Se x é False, então x, senão y |
y é executado apenas se x é True |
not x |
Se x é True, então False, senão True |
not tem menor prioridade do que operadores não booleanos |
Gostou desse artigo? Ele faz parte do Drops de programação, um conjunto de posts mais curtos voltados para fundamentos falando sobre alguns aspectos da linguagem Python e de programação em geral. Você pode ler mais desses artigos buscando a tag “drops” aqui no site.
Até a próxima!