Python and, or e not

Muitas perguntas do dia a dia são feitas de perguntas menores. "Posso entrar na festa?" depende de ser maior de idade e ter convite. "Ganho desconto?" depende de ser aniversário ou ser cliente VIP. "A padaria está fechada?" é o contrário de "está aberta". Para juntar e inverter perguntas, o Python tem três operadores com nomes em inglês bem simples: and ("e"), or ("ou") e not ("não"). Nesta aula você vai ver como eles funcionam, a ordem em que o Python os resolve, o truque do "curto-circuito" e um segredo que muda tudo: and e or nem sempre devolvem True ou False.

Você vai aprender
  • O and: verdadeiro só quando as duas partes são verdadeiras.
  • O or: verdadeiro quando pelo menos uma parte é verdadeira.
  • O not: inverte o valor.
  • A juntar comparações: idade >= 18 and tem_convite.
  • A ordem: primeiro not, depois and, por fim or.
  • O curto-circuito: quando o Python nem olha a segunda parte, e como isso evita erros.
  • Que and e or devolvem um dos valores: nome or "visitante".
  • A armadilha resposta == "s" or "S" e os erros de &&, || e !.

Os programas desta aula rodaram no Python 3.14 da máquina da Ana (usuária ana, computador notebook), e podem ser repetidos no editor do guia.


A ideia: as regras da portaria

Na portaria de uma festa, o segurança segue regras:

  • "Entra quem é maior de idade e tem convite." As duas coisas são exigidas. Faltou uma, não entra.
  • "Ganha pulseira VIP quem faz aniversário hoje ou é amigo do dono." Basta uma.
  • "Quem não está na lista paga entrada." O "não" inverte a pergunta.

É exatamente isso que fazem and, or e not. Eles trabalham com valores verdadeiros e falsos (aula Booleanos), quase sempre vindos de comparações (aula Comparações).

OperadorEm portuguêsÉ verdadeiro quando…
a and ba e b…os dois são verdadeiros
a or ba ou b…pelo menos um é verdadeiro
not anão a…a é falso

1. Os três operadores

aberta = True
tem_pao = False
print(aberta and tem_pao)
print(aberta or tem_pao)
print(not aberta)
print(not tem_pao)
$ python3 padaria_logica.py
False
True
False
True
aberta and tem_pao
"Está aberta e tem pão?" Está aberta, mas não tem pão: False. Para o and, uma parte falsa basta para tudo ser falso.
aberta or tem_pao
"Está aberta ou tem pão?" Está aberta: True. Para o or, uma parte verdadeira basta.
not aberta
"Não está aberta?" Como está aberta, False.
not tem_pao
"Não tem pão?" Verdade: True.

As tabelas da verdade

Como cada parte só pode ser True ou False, dá para testar todas as combinações:

$ python3 -q
>>> True and True
True
>>> True and False
False
>>> False and True
False
>>> False and False
False
>>> True or False
True
>>> False or False
False
>>> not True
False
>>> not False
True
aba and ba or b
TrueTrueTrueTrue
TrueFalseFalseTrue
FalseTrueFalseTrue
FalseFalseFalseFalse

Resumindo a tabela: o and só é True na primeira linha (tudo verdadeiro); o or só é False na última (tudo falso).

O "ou" do Python não é o "ou" do restaurante

Quando o garçom pergunta "batata ou salada?", ele quer dizer "um ou outro, não os dois". O or do Python é mais generoso: com as duas partes verdadeiras, a resposta também é True. Quem é aniversariante e amigo do dono também ganha a pulseira.


2. Juntando comparações

O uso mais comum é ligar duas ou mais comparações numa pergunta só:

idade = 20
tem_convite = True
pode_entrar = idade >= 18 and tem_convite
print("Pode entrar:", pode_entrar)
$ python3 festa.py
Pode entrar: True
aniversario = False
cliente_vip = True
tem_desconto = aniversario or cliente_vip
print("Tem desconto:", tem_desconto)
$ python3 desconto.py
Tem desconto: True

Repare na primeira: idade >= 18 and tem_convite. O Python resolve a comparação idade >= 18 primeiro (True) e só depois o and. As comparações sempre vêm antes de and, or e not, então você não precisa de parênteses em volta delas.

Missão: a regra da festa é "maior de idade e com convite". O Caio tem 20 anos, mas esqueceu o convite, e o programa deixou ele entrar. Conserte o operador.

idade = 20
tem_convite = False
pode_entrar = idade >= 18 or tem_convite
print("Pode entrar:", pode_entrar)
idade = 20
tem_convite = False
pode_entrar = idade >= 18 and tem_convite
print("Pode entrar:", pode_entrar)

3. Quem vem primeiro: not, and, or

Como na conta em que a multiplicação vem antes da soma, aqui também existe uma ordem: primeiro o not, depois o and, por último o or.

$ python3 -q
>>> True or False and False
True
>>> (True or False) and False
False
>>> not 5 == 5
False
True or False and False → True
O and vem antes: False and False é False; depois, True or False é True.
(True or False) and False → False
Os parênteses mudam a ordem: primeiro True or False (True); depois, True and False é False.
not 5 == 5 → False
A comparação vem antes do not: é not (5 == 5), ou seja, not True.

Quando uma pergunta mistura and e or, use parênteses, mesmo que não sejam necessários. "Desconto para quem é VIP, ou para quem compra mais de 10 itens num dia de promoção" fica assim: vip or (itens > 10 and promocao). Os parênteses mostram a regra para quem lê. A tabela completa da ordem está na aula Precedência dos Operadores.


4. O curto-circuito: o Python para assim que sabe

Pense no and: se a primeira parte for falsa, a resposta já é False, não importa a segunda. E no or: se a primeira parte for verdadeira, a resposta já é True. O Python sabe disso e, nesses casos, nem olha a segunda parte. É o que se chama de curto-circuito.

$ python3 -q
>>> True or 1 / 0
True
>>> False and 1 / 0
False

1 / 0 deveria dar ZeroDivisionError (aula Operadores Aritméticos). Não deu, porque o Python nunca chegou a fazer essa conta: a primeira parte já decidiu a resposta.

Para que serve: proteger a segunda pergunta

A Ana quer saber se a conta da festa, dividida entre as pessoas, passa de R$ 10 por cabeça. Mas pode não ter ninguém confirmado ainda:

total = 120
pessoas = 0
print(pessoas != 0 and total / pessoas > 10)
pessoas = 4
print(pessoas != 0 and total / pessoas > 10)
$ python3 divisao_segura.py
False
True

Com 0 pessoas, pessoas != 0 é False, e o and para ali: a divisão nem acontece. Com 4 pessoas, a primeira parte é verdadeira, e o Python faz a divisão (120 ÷ 4 = 30, que é maior que 10). A ordem das partes importa. Trocando, o erro aparece:

total = 120
pessoas = 0
print(total / pessoas > 10 and pessoas != 0)
$ python3 divisao_trocada.py
Traceback (most recent call last):
  File "/home/ana/divisao_trocada.py", line 3, in <module>
    print(total / pessoas > 10 and pessoas != 0)
          ~~~~~~^~~~~~~~~
ZeroDivisionError: division by zero

Agora a divisão é a primeira parte, e ela é feita antes de qualquer verificação. Regra prática: no and, ponha primeiro a pergunta que protege, depois a que poderia dar erro.


5. O segredo: and e or devolvem um dos valores

Até aqui, todos os exemplos usaram True e False. Mas and e or aceitam qualquer valor, porque todo valor é truthy ou falsy (aula Booleanos). E aí aparece o segredo: eles não devolvem True ou False. Devolvem um dos dois valores que receberam: o que decidiu a resposta.

$ python3 -q
>>> "Ana" or "visitante"
'Ana'
>>> "" or "visitante"
'visitante'
>>> None or 10
10
>>> 0 or ""
''
>>> 3 and 5
5
>>> 0 and 5
0
>>> "Ana" and "Bia"
'Bia'
OperadorSe o primeiro valor for…DevolveExemplo
a or btruthyo primeiro (nem olha o segundo)"Ana" or "visitante" → 'Ana'
falsyo segundo, seja ele qual for"" or "visitante" → 'visitante'; 0 or "" → ''
a and bfalsyo primeiro (nem olha o segundo)0 and 5 → 0
truthyo segundo, seja ele qual for3 and 5 → 5

É o curto-circuito de novo: o operador devolve o valor em que parou. Já o not é diferente: ele sempre devolve True ou False (not "texto" é False; not "" é True).

Para que serve: o valor padrão

O uso mais famoso é dar um valor "reserva" para quando o primeiro está vazio. Se a pessoa não digitar o nome, o programa a chama de visitante:

nome = input("Seu nome: ") or "visitante"
print("Olá,", nome)
$ python3 visitante.py
Seu nome: Ana
Olá, Ana
$ python3 visitante.py
Seu nome:
Olá, visitante

Na segunda vez, a Ana só apertou Enter. O input() devolveu "", que é falsy, e o or devolveu o segundo valor, "visitante". Cuidado só com um detalhe: o or troca qualquer valor falsy, incluindo o 0. Para uma quantidade, em que 0 é uma resposta válida, não use esse truque.

Missão: o nome está vazio, e o programa mostra Olá, !. Use o or para que, quando o nome estiver vazio, apareça visitante no lugar.

nome = ""
print("Olá, " + nome + "!")
nome = ""
print("Olá, " + (nome or "visitante") + "!")

Formas diferentes de fazer a mesma pergunta

PerguntaFormaQuando usar
Nota entre 0 e 10?0 <= nota <= 10O jeito mais curto e claro para uma faixa (aula Comparações)
nota >= 0 and nota <= 10Funciona igual; é como se escreve em outras linguagens
Fechada?not abertaPara inverter uma variável booleana
aberta == FalseFunciona, mas não é o costume. Prefira not
Respondeu "s" ou "S"?resposta == "s" or resposta == "S"Correto, repetindo a comparação inteira
resposta.lower() == "s"Mais curto: passa para minúscula antes (aula Métodos de Texto)
resposta in ("s", "S")Para várias respostas aceitas (aula is e in)
Valor padrãonome = texto or "visitante"Quando qualquer valor vazio deve ser trocado

Quando dá errado

resposta == "s" or "S": sempre "verdadeiro"

Em português, "a resposta é s ou S" soa perfeito. Em Python, não:

resposta = input("Quer sacola? (s/n) ")
quer_sacola = resposta == "s" or "S"
print("Quer sacola:", quer_sacola)
$ python3 sacola.py
Quer sacola? (s/n) n
Quer sacola: S

A Ana disse "n", e o resultado nem é True ou False: é S. O Python leu a linha como (resposta == "s") or "S": a comparação vem primeiro e deu False; o or, então, devolveu o segundo valor, o texto "S", que é truthy. Num if, isso conta como "sim" sempre, qualquer que seja a resposta. Sem mensagem de erro nenhuma.

Como consertar: repita a comparação inteira dos dois lados do or:

resposta = input("Quer sacola? (s/n) ")
quer_sacola = resposta == "s" or resposta == "S"
print("Quer sacola:", quer_sacola)
$ python3 sacola_certa.py
Quer sacola? (s/n) n
Quer sacola: False
$ python3 sacola_certa.py
Quer sacola? (s/n) S
Quer sacola: True
&&, || e ! de outras linguagens: SyntaxError

Em C, Java e JavaScript, "e", "ou" e "não" se escrevem &&, || e !. No Python, são palavras:

idade = 20
tem_convite = True
print(idade >= 18 && tem_convite)
$ python3 e_comercial.py
  File "/home/ana/e_comercial.py", line 3
    print(idade >= 18 && tem_convite)
                       ^
SyntaxError: invalid syntax
aniversario = False
cliente_vip = True
print(aniversario || cliente_vip)
$ python3 barras.py
  File "/home/ana/barras.py", line 3
    print(aniversario || cliente_vip)
                       ^
SyntaxError: invalid syntax
aberta = True
print(!aberta)
$ python3 exclamacao.py
  File "/home/ana/exclamacao.py", line 2
    print(!aberta)
          ^
SyntaxError: invalid syntax

Nos três casos, o chapeuzinho aponta o sinal que o Python não entendeu, e a mensagem é só invalid syntax, sem dica. Como consertar: and, or e not, por extenso e em minúsculas. (O ! só existe no Python dentro do !=, o "diferente".)

Cortar a segunda comparação: nota >= 0 and <= 10
nota = 8
print(nota >= 0 and <= 10)
$ python3 faixa_errada.py
  File "/home/ana/faixa_errada.py", line 2
    print(nota >= 0 and <= 10)
                        ^^
SyntaxError: invalid syntax

Em português, "nota maior ou igual a 0 e menor ou igual a 10" se entende. Para o Python, cada lado do and precisa ser uma pergunta completa, e <= 10 sozinho não diz quem é menor ou igual a 10. Como consertar: nota >= 0 and nota <= 10, ou, melhor ainda, 0 <= nota <= 10.

A ordem errada no curto-circuito: ZeroDivisionError

total / pessoas > 10 and pessoas != 0 dá ZeroDivisionError quando não há pessoas, como na seção 4: a divisão é feita antes da proteção. Como consertar: a pergunta que protege vem primeiro: pessoas != 0 and total / pessoas > 10.


Referência rápida

EscritaResultadoObservação
a and bVerdadeiro se os dois foremSe a é falsy, devolve a sem olhar b; senão, devolve b
a or bVerdadeiro se pelo menos um forSe a é truthy, devolve a sem olhar b; senão, devolve b
not aO contrário de aSempre True ou False
not → and → orA ordem; as comparações vêm antes dos três
pessoas != 0 and total / pessoas > 10Curto-circuito: a divisão só acontece se houver pessoas
texto or "padrão"Valor padrão quando texto está vazio
SintomaCausa provável
Uma pergunta com or é sempre "sim", ou devolve um textox == "s" or "S": repita a comparação, x == "s" or x == "S"
SyntaxError: invalid syntax apontando &&, || ou !Use and, or e not
SyntaxError: invalid syntax logo depois de um andA segunda comparação está incompleta: and nota <= 10
ZeroDivisionError numa pergunta com andA proteção (pessoas != 0) tem de vir antes da divisão
Um 0 foi trocado pelo valor padrãox or padrao troca qualquer falsy, até o zero

Exercícios

1. True ou False?

True and False → False or True → not (3 > 5) → True or True and False →

2. O que o or devolve?

Escreva o resultado como o modo interativo mostraria:

"" or "sem nome" → 0 or 7 →

3. A padaria dá brinde a quem compra mais de 10 pães e é cliente cadastrado. Qual expressão está certa?

4. Por que False and 1 / 0 não dá ZeroDivisionError?

5. A pessoa digitou n. Quanto vale resposta == "s" or "S"?

Missão final: a sacola

Missão: o editor vai responder n, mas o programa mostra Quer sacola: S. Conserte a pergunta para ela aceitar "s" ou "S" e responder False para qualquer outra coisa.

resposta = input("Quer sacola? (s/n) ")
quer_sacola = resposta == "s" or "S"
print("Quer sacola:", quer_sacola)
resposta = input("Quer sacola? (s/n) ")
quer_sacola = resposta == "s" or resposta == "S"
print("Quer sacola:", quer_sacola)

Resumo

  • and ("e"): verdadeiro só se as duas partes forem. or ("ou"): verdadeiro se pelo menos uma for. not ("não"): inverte.
  • As comparações são resolvidas antes; depois vem not, depois and, por fim or. Misturou and com or? Use parênteses.
  • Curto-circuito: o Python para assim que sabe a resposta. No and, ponha primeiro a pergunta que protege: pessoas != 0 and total / pessoas > 10.
  • and e or devolvem um dos valores, o que decidiu a resposta: "" or "visitante" é 'visitante'. O not sempre devolve True ou False.
  • nome = input(…) or "visitante" dá um valor padrão (cuidado: troca também o 0).
  • resposta == "s" or "S" está errado: repita a comparação, resposta == "s" or resposta == "S".
  • No Python não existem &&, || e !: dão SyntaxError.