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.
- 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, depoisand, por fimor. - O curto-circuito: quando o Python nem olha a segunda parte, e como isso evita erros.
- Que
andeordevolvem 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).
| Operador | Em português | É verdadeiro quando… |
|---|---|---|
a and b | a e b | …os dois são verdadeiros |
a or b | a ou b | …pelo menos um é verdadeiro |
not a | nã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 oand, uma parte falsa basta para tudo ser falso. - aberta or tem_pao
- "Está aberta ou tem pão?" Está aberta:
True. Para oor, 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
a | b | a and b | a or b |
|---|---|---|---|
True | True | True | True |
True | False | False | True |
False | True | False | True |
False | False | False | False |
Resumindo a tabela: o and só é True na primeira linha (tudo verdadeiro); o or só é False na última (tudo falso).
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
andvem 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'
| Operador | Se o primeiro valor for… | Devolve | Exemplo |
|---|---|---|---|
a or b | truthy | o primeiro (nem olha o segundo) | "Ana" or "visitante" → 'Ana' |
| falsy | o segundo, seja ele qual for | "" or "visitante" → 'visitante'; 0 or "" → '' | |
a and b | falsy | o primeiro (nem olha o segundo) | 0 and 5 → 0 |
| truthy | o segundo, seja ele qual for | 3 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
| Pergunta | Forma | Quando usar |
|---|---|---|
| Nota entre 0 e 10? | 0 <= nota <= 10 | O jeito mais curto e claro para uma faixa (aula Comparações) |
nota >= 0 and nota <= 10 | Funciona igual; é como se escreve em outras linguagens | |
| Fechada? | not aberta | Para inverter uma variável booleana |
aberta == False | Funciona, 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ão | nome = 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".)
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.
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
| Escrita | Resultado | Observação |
|---|---|---|
a and b | Verdadeiro se os dois forem | Se a é falsy, devolve a sem olhar b; senão, devolve b |
a or b | Verdadeiro se pelo menos um for | Se a é truthy, devolve a sem olhar b; senão, devolve b |
not a | O contrário de a | Sempre True ou False |
not → and → or | A ordem; as comparações vêm antes dos três | |
pessoas != 0 and total / pessoas > 10 | Curto-circuito: a divisão só acontece se houver pessoas | |
texto or "padrão" | Valor padrão quando texto está vazio |
| Sintoma | Causa provável |
|---|---|
Uma pergunta com or é sempre "sim", ou devolve um texto | x == "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 and | A segunda comparação está incompleta: and nota <= 10 |
ZeroDivisionError numa pergunta com and | A proteção (pessoas != 0) tem de vir antes da divisão |
Um 0 foi trocado pelo valor padrão | x or padrao troca qualquer falsy, até o zero |
Exercícios
1. True ou False?
2. O que o or devolve?
Escreva o resultado como o modo interativo mostraria:
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, depoisand, por fimor. Misturouandcomor? 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. andeordevolvem um dos valores, o que decidiu a resposta:"" or "visitante"é'visitante'. Onotsempre devolveTrueouFalse.nome = input(…) or "visitante"dá um valor padrão (cuidado: troca também o0).resposta == "s" or "S"está errado: repita a comparação,resposta == "s" or resposta == "S".- No Python não existem
&&,||e!: dãoSyntaxError.