Resposta rápida
O operador ternário do Python é o if/else em uma linha: uma expressão que escolhe entre dois valores com a sintaxe valor_se_verdadeiro if condição else valor_se_falso. Ele retorna um valor, então pode ser atribuído, passado como argumento ou usado dentro de f-strings e comprehensions.
1
2
3
idade = 20
status = "adulto" if idade >= 18 else "menor"
print(status) # adulto
Resumo em 30 segundos:
- Não existe
? :em Python: a forma éa if condição else b(PEP 308, Python 2.5). - A condição é avaliada primeiro e só um ramo é executado.
- O
elseé obrigatório e cada ramo precisa ser uma expressão (nada de=,passouraise). -
valor or padraonão é a mesma coisa: ele descarta0e"". - Ternário aninhado funciona, mas com 3+ caminhos prefira
if/elif/else.
Salve salve Pythonista!
O operador ternário é o if/else que cabe em uma linha. Parece simples, mas tem detalhes que caem em prova e derrubam código em produção: ordem de avaliação, precedência, a armadilha do or com valores falsy e o ternário aninhado.
Se você ainda não domina o if, elif e else em bloco, comece pelo nosso guia de estruturas condicionais no Python. Aqui vamos bem mais fundo no ternário, com todos os exemplos executados no Python 3.10 e a saída real.
Então… Bora pro post! ![]()
Vá Direto ao Assunto…
- O que é o operador ternário no Python
- Sintaxe: valor if condição else outro valor
- Ordem de avaliação: só um ramo é executado
- Ternário é expressão, não comando
- Onde o ternário brilha
- Ternário aninhado: por que evitar
- Ternário vs or e and: a armadilha dos valores falsy
- Formas antigas: (a, b)[cond] e cond and a or b
- Ternário vs dicionário de despacho vs match/case
- Operador ternário em C, Java e JavaScript vs Python
- Quando usar ternário, if/else, dicionário, match/case ou or
- Legibilidade e o que os linters dizem
- Erros comuns
- Exercícios resolvidos
O que é o operador ternário no Python
O operador ternário (nome oficial: expressão condicional) é uma forma de escolher entre dois valores de acordo com uma condição, tudo em uma única expressão. O nome “ternário” vem de ele ter três partes: o valor se verdadeiro, a condição e o valor se falso.
Compare as duas versões abaixo. Elas fazem exatamente a mesma coisa:
1
2
3
4
5
6
7
8
9
10
11
12
idade = 15
# Versão em bloco (4 linhas)
if idade >= 18:
status = "adulto"
else:
status = "menor"
print(status)
# Versão com operador ternário (1 linha)
status = "adulto" if idade >= 18 else "menor"
print(status)
1
2
menor
menor
A diferença fundamental: o if em bloco é um comando (statement), que executa código. O ternário é uma expressão, que produz um valor. E um valor pode ir para qualquer lugar onde o Python espera um valor: numa atribuição, num print(), num return, dentro de uma lista.
A documentação oficial chama isso de conditional expression e a definição completa está na seção “Conditional expressions” da referência da linguagem.
Sintaxe: valor if condição else outro valor
A sintaxe é:
1
resultado = valor_se_verdadeiro if condição else valor_se_falso
Uma dica para memorizar: leia em voz alta como uma frase em inglês. "adulto" if idade >= 18 else "menor" vira “adulto, se a idade for maior ou igual a 18, senão menor”.
Como é uma expressão, o resultado pode ser usado direto, sem passar por uma variável:
1
2
3
4
5
6
temperatura = 31
print("Calor" if temperatura > 28 else "Agradável")
mensagem = "Leve um casaco" if temperatura < 15 else "Pode ir de camiseta"
print(mensagem.upper())
print(len("sim" if temperatura > 28 else "não"))
1
2
3
Calor
PODE IR DE CAMISETA
3
A condição pode ser qualquer expressão: comparações, and, or, not, in ou até um valor sozinho, que será avaliado pela regra de truthiness (0, "", [] e None contam como falso). Se quiser revisar esses operadores, veja o post sobre operadores aritméticos e lógicos em Python.
Ordem de avaliação: só um ramo é executado
Apesar de a condição estar escrita no meio, o Python avalia a condição primeiro. Depois, avalia apenas o ramo escolhido. O outro nunca é executado. Dá para provar isso com duas funções que avisam quando são chamadas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def ramo_verdadeiro():
print(" -> avaliou o ramo verdadeiro")
return "V"
def ramo_falso():
print(" -> avaliou o ramo falso")
return "F"
for condicao in (True, False):
print(f"condicao = {condicao}")
resultado = ramo_verdadeiro() if condicao else ramo_falso()
print(f" resultado = {resultado}")
1
2
3
4
5
6
condicao = True
-> avaliou o ramo verdadeiro
resultado = V
condicao = False
-> avaliou o ramo falso
resultado = F
Esse comportamento de curto-circuito tem uso prático: o ramo “perigoso” só roda quando é seguro. O clássico é evitar divisão por zero:
1
2
3
4
5
6
def media(total, quantidade):
return total / quantidade if quantidade != 0 else 0.0
print(media(30, 4))
print(media(30, 0))
1
2
7.5
0.0
Precedência: o ternário “engole” o resto da linha
O ternário tem uma das prioridades mais baixas do Python. Na tabela de precedência oficial, abaixo dele só estão lambda e o operador morsa :=. Na prática, isso significa que +, *, comparações, and e or são resolvidos antes do if/else. Veja o bug que isso causa:
1
2
3
4
5
6
7
8
9
10
11
12
nota = 4
# O ternário tem prioridade mais baixa que o +
texto = "Situação: " + "aprovado" if nota >= 6 else "reprovado"
print(texto)
# Com parênteses, o + recebe o resultado do ternário
texto = "Situação: " + ("aprovado" if nota >= 6 else "reprovado")
print(texto)
x = 10
print(x * 2 if x > 5 else x + 1) # (x * 2) if ... else (x + 1)
1
2
3
reprovado
Situação: reprovado
20
A primeira linha foi lida como ("Situação: " + "aprovado") if nota >= 6 else "reprovado", por isso o prefixo sumiu. Regra prática: se o ternário faz parte de uma expressão maior, coloque parênteses em volta dele.
Ternário é expressão, não comando
Cada ramo do ternário precisa ser uma expressão (algo que produz valor). Por isso não dá para colocar ali uma atribuição com =, um pass, um return ou um raise. E o else é obrigatório: uma expressão sempre precisa devolver algum valor. Você vai ver as mensagens de erro exatas na seção Erros comuns.
Chamar funções nos ramos, por outro lado, é permitido, porque uma chamada é uma expressão. Mas cuidado com o uso “para executar coisas”:
1
2
3
4
5
6
7
8
9
10
logado = False
# Funciona, mas é um "if disfarçado": o valor (None) é jogado fora
print("Bem-vindo de volta!") if logado else print("Faça login")
# Mais claro:
if logado:
print("Bem-vindo de volta!")
else:
print("Faça login")
1
2
Faça login
Faça login
A primeira versão roda, mas usa o ternário só pelos efeitos colaterais e descarta o resultado. Isso confunde quem lê. Use o ternário quando você quer um valor; quando quer executar ações, use o if em bloco.
Está curtindo esse conteúdo? ![]()
Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?
Onde o ternário brilha
Por ser uma expressão, o ternário encaixa em lugares onde um if em bloco simplesmente não cabe.
Ternário dentro de f-string
Perfeito para plural, sinais e rótulos em mensagens. Se você ainda não usa f-strings, veja o post sobre f-strings no Python.
1
2
3
4
5
6
7
8
itens = 1
print(f"Você tem {itens} {'item' if itens == 1 else 'itens'} no carrinho")
itens = 3
print(f"Você tem {itens} {'item' if itens == 1 else 'itens'} no carrinho")
saldo = -250.5
print(f"Saldo: R$ {abs(saldo):.2f} {'(negativo)' if saldo < 0 else ''}")
1
2
3
Você tem 1 item no carrinho
Você tem 3 itens no carrinho
Saldo: R$ 250.50 (negativo)
Repare nas aspas: a f-string usa aspas duplas e o ternário dentro dela usa simples. Até o Python 3.11, repetir as mesmas aspas dentro das chaves é SyntaxError (no 3.10 a mensagem é SyntaxError: f-string: expecting '}'). A partir do Python 3.12 (PEP 701) isso passou a ser permitido, mas alternar as aspas continua sendo o jeito que funciona em qualquer versão.
Ternário em list comprehension e dict comprehension
Aqui mora uma dúvida clássica: onde vai o if? A regra é simples:
-
Ternário (
if ... else) antes dofor: transforma todos os itens. -
ifsozinho depois dofor: filtra itens (e não aceitaelse).
1
2
3
4
5
6
7
8
9
10
11
12
numeros = [1, 2, 3, 4, 5, 6]
# if-else ANTES do for: transforma todos os itens
rotulos = ["par" if n % 2 == 0 else "ímpar" for n in numeros]
print(rotulos)
# if DEPOIS do for: filtra (não tem else)
pares = [n for n in numeros if n % 2 == 0]
print(pares)
# Os dois juntos: filtra os maiores que 2 e rotula
print(["par" if n % 2 == 0 else "ímpar" for n in numeros if n > 2])
1
2
3
['ímpar', 'par', 'ímpar', 'par', 'ímpar', 'par']
[2, 4, 6]
['ímpar', 'par', 'ímpar', 'par']
O mesmo vale para dicionários:
1
2
3
4
notas = {"Ana": 8.5, "Bruno": 5.0, "Carla": 6.0}
situacao = {nome: "aprovado" if nota >= 6 else "reprovado" for nome, nota in notas.items()}
print(situacao)
1
{'Ana': 'aprovado', 'Bruno': 'reprovado', 'Carla': 'aprovado'}
Para aprofundar, veja os posts sobre list comprehensions e dict comprehensions.
Ternário em lambda e em argumentos de função
Uma lambda só aceita uma expressão, então o ternário é a única forma de colocar uma decisão dentro dela. Ele também aparece muito como argumento de função e na chave de ordenação:
1
2
3
4
5
6
7
8
9
10
11
12
13
numeros = [5, -2, 0, 8]
sinais = list(map(lambda n: "negativo" if n < 0 else "não negativo", numeros))
print(sinais)
tarefas = [
{"nome": "responder email", "urgente": False},
{"nome": "corrigir bug em produção", "urgente": True},
{"nome": "atualizar README", "urgente": False},
]
# Urgentes primeiro: a chave vale 0 para urgente e 1 para o resto
for t in sorted(tarefas, key=lambda t: 0 if t["urgente"] else 1):
print(t["nome"])
1
2
3
4
['não negativo', 'negativo', 'não negativo', 'não negativo']
corrigir bug em produção
responder email
atualizar README
Mais sobre lambda no post de funções lambda no Python.
Em argumentos nomeados, o ternário evita criar variáveis temporárias:
1
2
3
4
5
6
7
8
9
10
def saudar(nome, formal):
print(f"{'Prezado(a)' if formal else 'Oi'}, {nome}!")
saudar("Marina", formal=True)
saudar("Marina", formal=False)
modo_verboso = False
print("Processando...", end="\n" if modo_verboso else " ")
print("ok")
1
2
3
Prezado(a), Marina!
Oi, Marina!
Processando... ok
Ternário no return
Funções curtas que escolhem entre dois resultados ficam muito limpas com return + ternário:
1
2
3
4
5
6
7
8
9
10
11
def maior(a, b):
return a if a >= b else b
def sinal(n):
return -1 if n < 0 else 1
print(maior(7, 12), maior(9, 3))
print(sinal(-8), sinal(4))
print(max(7, 12))
1
2
3
12 9
-1 1
12
A última linha é um lembrete: quando o ternário só escolhe o maior ou o menor de dois valores, max() e min() fazem o mesmo de forma mais direta. O ruff tem até uma regra para isso (FURB136), como você vai ver mais adiante.
Ternário aninhado: por que evitar
Como um ramo do ternário pode ser qualquer expressão, ele pode ser outro ternário. O Python agrupa da direita para a esquerda:
1
2
3
4
5
6
7
8
nota = 7.5
conceito = "A" if nota >= 9 else "B" if nota >= 7 else "C" if nota >= 5 else "D"
print(conceito)
# O Python lê da direita para a esquerda (associatividade à direita):
conceito = "A" if nota >= 9 else ("B" if nota >= 7 else ("C" if nota >= 5 else "D"))
print(conceito)
1
2
B
B
Funciona e o resultado está certo, mas olhe de novo para a linha 3. Para entender qual conceito sai, você precisa ler a linha inteira, contar os else e montar os parênteses de cabeça. Agora compare com a mesma lógica em bloco:
1
2
3
4
5
6
7
8
9
10
11
def conceito(nota):
if nota >= 9:
return "A"
elif nota >= 7:
return "B"
elif nota >= 5:
return "C"
return "D"
print([conceito(n) for n in (9.5, 7.5, 5.0, 3.2)])
1
['A', 'B', 'C', 'D']
Cada faixa fica numa linha e acrescentar uma nova não exige reescrever tudo. Regra prática: dois caminhos, ternário; três ou mais, if/elif/else (ou um dicionário, como veremos abaixo).
Ternário vs or e and: a armadilha dos valores falsy
É muito comum ver or usado como “valor padrão”: nome = nome_digitado or "Anônimo". Isso funciona porque o or devolve o primeiro valor verdadeiro. O problema é que todo valor falsy é descartado, não só o None:
1
2
3
4
5
6
7
8
def conectar(porta=None):
porta_final = porta or 8080
print(f"Conectando na porta {porta_final}")
conectar() # sem porta: usa o padrão
conectar(5432) # porta informada
conectar(0) # 0 é falsy: o "or" ignora e usa 8080!
1
2
3
Conectando na porta 8080
Conectando na porta 5432
Conectando na porta 8080
Se 0 (ou "", ou []) for um valor legítimo, use o ternário com um teste explícito:
1
2
3
4
5
6
7
8
def conectar(porta=None):
porta_final = porta if porta is not None else 8080
print(f"Conectando na porta {porta_final}")
conectar()
conectar(5432)
conectar(0) # agora o 0 é respeitado
1
2
3
Conectando na porta 8080
Conectando na porta 5432
Conectando na porta 0
Resumindo: x or padrao equivale a x if x else padrao (teste de truthiness). Quando você quer testar “foi informado ou não”, o teste certo é is not None, e aí só o ternário resolve.
Formas antigas: (a, b)[cond] e cond and a or b
O ternário só chegou na versão 2.5, em 2006. Antes disso, as pessoas improvisavam com dois truques que ainda aparecem em código legado. Vale conhecer para reconhecer, não para usar.
O idioma cond and a or b
A ideia era: se cond for verdadeira, cond and a vale a, e o or devolve a. Se for falsa, o or devolve b. O defeito aparece quando a é falsy:
1
2
3
4
5
6
7
8
9
estoque = 0
tem_estoque = True
# Idioma antigo: condição and valor_se_verdadeiro or valor_se_falso
exibir = tem_estoque and estoque or "indisponível"
print(exibir) # esperava 0, veio "indisponível"
exibir = estoque if tem_estoque else "indisponível"
print(exibir)
1
2
indisponível
0
A própria PEP 308, que criou o ternário, cita esse problema: o idioma retorna o segundo valor quando o primeiro é falso. Foi exatamente essa fonte de bugs que motivou a nova sintaxe.
O truque da tupla (a, b)[cond]
Como False == 0 e True == 1, dá para usar a condição como índice:
1
2
3
4
5
6
idade = 20
# (valor_se_falso, valor_se_verdadeiro)[condição]
status = ("menor", "adulto")[idade >= 18]
print(status)
print(True == 1, False == 0)
1
2
adulto
True True
Três problemas: a ordem é invertida (o valor falso vem primeiro), a leitura é obscura e, o pior, os dois valores são calculados antes da escolha, porque a tupla inteira é montada primeiro. Não existe curto-circuito aqui, e isso quebra o exemplo da divisão segura (veja em Erros comuns).
Ternário vs dicionário de despacho vs match/case
Quando a decisão deixa de ser “isto ou aquilo” e vira “um entre vários”, existem ferramentas melhores do que empilhar ternários.
Dicionário de valores. Se cada opção mapeia para um valor fixo, um dicionário com .get() e um padrão resolve em uma linha e escala para dezenas de opções:
1
2
3
4
5
6
7
8
FRETES = {"PAC": 25.90, "SEDEX": 49.90, "RETIRADA": 0.0}
def calcular_frete(modalidade):
return FRETES.get(modalidade, 35.0)
print(calcular_frete("SEDEX"))
print(calcular_frete("MOTOBOY")) # não cadastrada: valor padrão
1
2
49.9
35.0
Dicionário de despacho. Se cada opção precisa executar algo diferente, guarde funções no dicionário (lembre que funções são objetos em Python; revise no post de funções em Python):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def somar(a, b):
return a + b
def subtrair(a, b):
return a - b
def multiplicar(a, b):
return a * b
OPERACOES = {"+": somar, "-": subtrair, "*": multiplicar}
for op in ("+", "-", "*"):
print(op, OPERACOES[op](10, 4))
1
2
3
+ 14
- 6
* 40
match/case (Python 3.10+). Quando a decisão depende da forma dos dados (tamanho de uma lista, chaves de um dicionário, tipos) ou precisa de guardas, o match/case é a ferramenta certa:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def descrever(comando):
match comando.split():
case ["sair"]:
return "Encerrando o programa"
case ["ir", direcao] if direcao in ("norte", "sul"):
return f"Andando para o {direcao}"
case ["pegar", *itens]:
return f"Pegando {len(itens)} item(ns): {', '.join(itens)}"
case _:
return "Comando desconhecido"
print(descrever("sair"))
print(descrever("ir norte"))
print(descrever("pegar chave mapa"))
print(descrever("voar"))
1
2
3
4
Encerrando o programa
Andando para o norte
Pegando 2 item(ns): chave, mapa
Comando desconhecido
Nenhum ternário, por mais aninhado, expressa isso com clareza. Veja mais sobre o match/case no post sobre o Python 3.10.
Operador ternário em C, Java e JavaScript vs Python
Quem vem de outra linguagem costuma procurar o ? :. Em C, Java e JavaScript ele existe e a condição vem primeiro:
1
2
3
const idade = 20;
const status = idade >= 18 ? "adulto" : "menor";
console.log(status); // adulto
1
2
int idade = 20;
const char *status = idade >= 18 ? "adulto" : "menor"; /* "adulto" */
Em Java a sintaxe é idêntica à do C. Em Python, o ? : não existe e gera SyntaxError. A PEP 308 discutiu a sintaxe C ? x : y e a rejeitou por dois motivos: os dois-pontos já têm muitos usos em Python e a notação é difícil de entender para quem não vem de linguagens derivadas do C. A escolha final foi x if C else y, decidida por Guido van Rossum em setembro de 2005.
| Aspecto | C, Java, JavaScript | Python |
|---|---|---|
| Sintaxe | cond ? a : b |
a if cond else b |
| O que vem primeiro no texto | A condição | O valor se verdadeiro |
| O que é avaliado primeiro | A condição | A condição |
| Avalia só um ramo | Sim | Sim |
| Aninhamento | Associa à direita | Associa à direita |
| Desde quando | Desde as primeiras versões | Python 2.5 (2006), PEP 308 |
Saber escolher a ferramenta certa entre essas opções vem da prática - é esse tipo de julgamento que você desenvolve na Jornada Python, resolvendo projetos do zero ao avançado:
Quando usar ternário, if/else, dicionário, match/case ou or
Esta é a tabela para consultar na hora de decidir:
| Situação | Use | Exemplo |
|---|---|---|
| Escolher entre dois valores simples | Ternário | "par" if n % 2 == 0 else "ímpar" |
| Decisão dentro de f-string, lambda, comprehension ou argumento | Ternário | f"{n} {'item' if n == 1 else 'itens'}" |
Executar ações (várias linhas, print, return, raise) |
if/else em bloco |
if erro: raise ValueError(...) |
| Três ou mais faixas ou condições |
if/elif/else em bloco |
Conceito A, B, C, D por nota |
| Muitas opções que mapeiam para valores fixos | Dicionário com .get()
|
FRETES.get(tipo, 35.0) |
| Muitas opções que executam ações diferentes | Dicionário de despacho | OPERACOES[op](a, b) |
| Decidir pela forma dos dados, com guardas |
match/case (3.10+) |
case ["ir", direcao]: |
| Valor padrão quando qualquer falsy deve ser trocado | or |
nome or "Anônimo" |
Valor padrão quando 0 ou "" são válidos |
Ternário com is not None
|
porta if porta is not None else 8080 |
| Pegar o maior ou menor de dois valores |
max() / min()
|
max(a, b) |
Legibilidade e o que os linters dizem
Ternário não deixa o código ilegível por si só: ternário curto é idiomático; longo ou aninhado é que atrapalha. As ferramentas da comunidade pensam assim.
O ruff, um dos linters mais populares do ecossistema Python, tem a regra SIM108, que faz o caminho contrário do que muita gente espera: ela sugere trocar um if/else em bloco que só atribui uma variável por um ternário. Testamos com o ruff 0.16.9, instalado num ambiente virtual (se quiser um jeito rápido de instalar ferramentas assim, veja o post sobre o uv). Dado este arquivo:
1
2
3
4
5
6
7
8
idade = 20
if idade >= 18:
status = "adulto"
else:
status = "menor"
print(status)
A saída do ruff check --select SIM108 --output-format concise sim108.py foi:
1
2
sim108.py:3:1: SIM108 Use ternary operator `status = "adulto" if idade >= 18 else "menor"` instead of `if`-`else`-block
Found 1 error.
Detalhes importantes sobre essa regra:
- A própria documentação da SIM108 diz que ela é opinativa e que ternários podem dificultar a medição de cobertura de testes por linha (as duas saídas ficam na mesma linha).
- Ela não dispara se a linha resultante passar do limite de tamanho configurado. Ou seja: o ruff só sugere o ternário quando ele fica curto.
- No ruff 0.16.9, a SIM108 não vem ligada por padrão. Para ativá-la, junto com a FURB110 (que troca
x if x else yporx or y), use opyproject.toml:
1
2
[tool.ruff.lint]
extend-select = ["SIM108", "FURB110"]
Outras regras que vêm ligadas por padrão nessa versão pegam ternários desnecessários:
| Regra | Detecta | Troque por |
|---|---|---|
| SIM210 | True if cond else False |
bool(cond) ou só cond
|
| SIM211 | False if cond else True |
not cond |
| FURB136 | a if a >= b else b |
max(a, b) |
| FURB110 | x if x else y |
x or y |
A FURB110 é segura justamente porque x if x else y já testa truthiness, igualzinho ao or. Ela não vai sugerir trocar x if x is not None else y, porque aí o comportamento seria diferente.
Para regras gerais de estilo (espaços, tamanho de linha, nomes), vale ler o nosso post sobre o guia de estilos PEP 8.
Erros comuns
Os tracebacks abaixo foram gerados no Python 3.10 (a linha final é a mesma no 3.14, exceto onde indicado).
Esquecer o else (SyntaxError)
1
2
idade = 20
status = "adulto" if idade >= 18
1
SyntaxError: expected 'else' after 'if' expression
Correção: uma expressão sempre produz um valor, então os dois ramos são obrigatórios. Se não há valor para o caso falso, use um if em bloco ou None explícito: status = "adulto" if idade >= 18 else None.
Usar a sintaxe ? : de outras linguagens (SyntaxError)
1
2
idade = 20
status = idade >= 18 ? "adulto" : "menor"
1
SyntaxError: invalid syntax
Correção: em Python a forma é status = "adulto" if idade >= 18 else "menor".
Colocar uma atribuição dentro de um ramo (SyntaxError)
1
2
idade = 20
status = "adulto" if idade >= 18 else status = "menor"
1
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Correção: a atribuição fica fora, à esquerda, uma única vez: status = "adulto" if idade >= 18 else "menor". O mesmo vale para raise, pass e return dentro de um ramo: no 3.10 dão SyntaxError: invalid syntax, e no 3.14 a mensagem é mais clara, SyntaxError: expected expression after 'else', but statement is given. Para lançar exceção, use um if em bloco.
Usar o truque da tupla e perder o curto-circuito (ZeroDivisionError)
1
2
3
quantidade = 0
media = (0.0, 30 / quantidade)[quantidade != 0]
print(media)
1
ZeroDivisionError: division by zero
Correção: a tupla calcula os dois itens antes de escolher, então 30 / 0 roda de qualquer jeito. O ternário só avalia o ramo escolhido: media = 30 / quantidade if quantidade != 0 else 0.0.
Esquecer os parênteses numa expressão maior (sem erro, resultado errado)
1
2
nota = 4
print("Situação: " + "aprovado" if nota >= 6 else "reprovado")
1
reprovado
Esse é o mais traiçoeiro, porque não há traceback: o + é resolvido antes do ternário e o prefixo some quando a condição é falsa. Correção: "Situação: " + ("aprovado" if nota >= 6 else "reprovado").
Exercícios resolvidos
Tente resolver cada exercício antes de abrir a solução. Todos os códigos foram executados e as saídas conferidas. Para praticar outros assuntos, veja a nossa página de exercícios de Python resolvidos.
Exercício 1. Dado n = 7, imprima "par" ou "ímpar" usando um operador ternário em uma única linha.
Ver solução
1
2
n = 7
print("par" if n % 2 == 0 else "ímpar")
Saída: ímpar
O resto da divisão por 2 (%) é 0 para pares. Como 7 % 2 vale 1, a condição é falsa e o ramo do else é o escolhido.
Exercício 2. Sem usar abs(), calcule o valor absoluto de x = -15 com um ternário.
Ver solução
1
2
3
x = -15
modulo = x if x >= 0 else -x
print(modulo)
Saída: 15
Se o número já é positivo (ou zero), ele fica como está; se é negativo, trocamos o sinal com -x.
Exercício 3. Dada a lista valores = [3, -1, 8, -5, 0], crie uma nova lista em que todo número negativo vira 0 e os demais ficam iguais. Use list comprehension.
Ver solução
1
2
3
valores = [3, -1, 8, -5, 0]
ajustados = [v if v > 0 else 0 for v in valores]
print(ajustados)
Saída: [3, 0, 8, 0, 0]
Como queremos transformar todos os itens (e não filtrar), o ternário vai antes do for. Uma alternativa equivalente e ainda mais curta é [max(v, 0) for v in valores].
Exercício 4. Para as quantidades 0, 1 e 5, imprima "<qtd> aluno" ou "<qtd> alunos", usando o ternário dentro de uma f-string.
Ver solução
1
2
for qtd in (0, 1, 5):
print(f"{qtd} {'aluno' if qtd == 1 else 'alunos'}")
Saída:
1
2
3
0 alunos
1 aluno
5 alunos
Em português, só o 1 fica no singular (zero também é plural), por isso a condição é qtd == 1. As aspas simples dentro da f-string de aspas duplas funcionam em qualquer versão do Python 3.
Exercício 5. A função abaixo deveria aplicar 10% de desconto por padrão, mas respeitar um desconto de 0% quando ele for informado. Encontre o bug e corrija.
1
2
3
4
5
6
7
def preco_final(preco, desconto=None):
desconto = desconto or 10
return preco * (1 - desconto / 100)
print(preco_final(200))
print(preco_final(200, 0))
Ver solução
O código original imprime 180.0 nas duas chamadas: o 0 é falsy e o or o substitui por 10. A correção é testar None explicitamente:
1
2
3
4
5
6
7
def preco_final(preco, desconto=None):
desconto = desconto if desconto is not None else 10
return preco * (1 - desconto / 100)
print(preco_final(200))
print(preco_final(200, 0))
Saída:
1
2
180.0
200.0
Agora o padrão só entra quando nenhum desconto foi passado, e o desconto zero é respeitado.
Exercício 6. Refatore o ternário aninhado abaixo usando um dicionário, mantendo 0.05 como taxa padrão para formas de pagamento desconhecidas.
1
2
3
forma = "boleto"
taxa = 0.0 if forma == "pix" else 0.02 if forma == "boleto" else 0.035 if forma == "cartao" else 0.05
print(taxa) # 0.02
Ver solução
1
2
3
4
5
6
7
TAXAS = {"pix": 0.0, "boleto": 0.02, "cartao": 0.035}
def taxa(forma):
return TAXAS.get(forma, 0.05)
print(taxa("boleto"), taxa("cartao"), taxa("cheque"))
Saída: 0.02 0.035 0.05
Cada forma de pagamento vira uma entrada do dicionário e o segundo argumento do .get() faz o papel do último else. Adicionar uma nova forma agora é só acrescentar uma chave.
Exercício 7 (estilo prova). Qual é a saída do código abaixo?
1
2
x = 2
print("A" if x > 3 else "B" if x > 1 else "C")
a) A
b) B
c) C
d) SyntaxError, pois não existe elif no ternário
Ver solução
Saída: B
Resposta: b. O ternário aninhado é válido e associa à direita: "A" if x > 3 else ("B" if x > 1 else "C"). Como 2 > 3 é falso, vale o ternário interno; 2 > 1 é verdadeiro, então sai "B". A alternativa d é a pegadinha: realmente não existe elif, mas o aninhamento substitui essa função.
Exercício 8 (estilo prova). Qual é a saída do código abaixo?
1
2
n = 3
print("Situação: " + "zero" if n == 0 else "não zero")
a) Situação: não zero
b) não zero
c) Situação: zero
d) TypeError
Ver solução
Saída: não zero
Resposta: b. O ternário tem prioridade mais baixa que o +, então o Python lê ("Situação: " + "zero") if n == 0 else "não zero". Como n == 0 é falso, sai só "não zero", sem o prefixo. Para obter a alternativa a, seria preciso escrever "Situação: " + ("zero" if n == 0 else "não zero").
Quer praticar condicionais, funções e o resto dos fundamentos com projetos guiados? Conheça o nosso curso de Python completo.
Conclusão
Neste guia do operador ternário no Python, você aprendeu:
- A sintaxe
a if condição else b: uma expressão que avalia a condição primeiro e só um ramo. - Que a precedência é baixa: dentro de expressões maiores, use parênteses.
- Onde ele brilha (f-strings, comprehensions,
lambda,return) e por que evitar o aninhado. - Que
ordescarta0e"", eis not Noneresolve. - Que
cond and a or be(a, b)[cond]ficaram no passado, e o que o ruff sugere.
A regra de ouro: use o ternário para escolher um valor entre dois, de forma curta. Se precisar de mais do que isso, o if em bloco é seu amigo.
Se ficou com alguma dúvida, fique à vontade para deixar um comentário no box aqui embaixo! Será um prazer te responder! ![]()
Perguntas frequentes
Como fazer um if else em uma linha no Python?
Use o operador ternário (expressão condicional): valor_se_verdadeiro if condição else valor_se_falso. Exemplo: status = "adulto" if idade >= 18 else "menor". O Python avalia a condição primeiro e retorna só um dos dois valores. O else é obrigatório.
O Python tem o operador ternário ? : como C, Java e JavaScript?
Não. Escrever condição ? a : b em Python gera SyntaxError: invalid syntax. O equivalente em Python é a if condição else b, criado pela PEP 308 e disponível desde o Python 2.5. Repare que a ordem muda: em Python o valor verdadeiro vem antes da condição.
O operador ternário avalia os dois lados?
Não. Em x if C else y, o Python avalia primeiro a condição C e depois apenas um dos ramos: x se C for verdadeira, y se for falsa. O outro ramo nunca é executado. Por isso total / qtd if qtd != 0 else 0 é seguro e não gera divisão por zero.
Qual a diferença entre usar o ternário e usar or para valor padrão?
valor or padrao troca o valor por padrao sempre que ele for falsy, ou seja, também quando for 0, string vazia "" ou lista vazia. Se esses valores forem válidos, use o ternário com teste explícito: valor if valor is not None else padrao. O or só é seguro quando qualquer valor falsy deve mesmo ser substituído.
Posso usar elif no operador ternário?
Não existe elif dentro do ternário, mas é possível aninhar: "A" if n >= 9 else "B" if n >= 7 else "C". O Python agrupa da direita para a esquerda. Funciona, mas com três ou mais caminhos a leitura piora muito, e o recomendado é voltar para o if/elif/else em bloco, um dicionário ou match/case.
Qual a saída de print(“A” if x > 3 else “B” if x > 1 else “C”) quando x vale 2?
A saída é B. O ternário aninhado é lido como "A" if x > 3 else ("B" if x > 1 else "C"). Como 2 > 3 é falso, o Python passa para o ternário interno; 2 > 1 é verdadeiro, então o resultado é "B". O ramo "C" nem chega a ser avaliado.
Posso usar o operador ternário dentro de uma list comprehension?
Sim. Para transformar todos os itens, coloque o ternário antes do for: ["par" if n % 2 == 0 else "ímpar" for n in numeros]. Já o if depois do for (sem else) serve para filtrar: [n for n in numeros if n % 2 == 0]. Os dois podem aparecer juntos na mesma comprehension.
É errado usar o operador ternário? Deixa o código menos legível?
Não é errado. Para escolher entre dois valores simples, o ternário é idiomático e linters como o ruff chegam a sugerir trocá-lo pelo if/else em bloco (regra SIM108). O problema é abusar: ternários aninhados, condições longas ou ramos com efeitos colaterais, como chamar print() nos dois lados. Nesses casos, o if em bloco é mais claro.
"Porque o Senhor dá a sabedoria, e da sua boca vem a inteligência e o entendimento" Pv 2:6