A linguagem Python suporta os seguintes operadores 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.
Tópicos
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. Fiz também um material ensinando um pouco de lógica booleana com exercícios para praticar que pode ser acessado 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 Python Drops, 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!