Operador Ternário no Python: o if/else em uma linha

Cansado de programar?

Conheça a melhor e mais completa formação de Python e Django e sinta-se um programador verdadeiramente competente. Além de Python e Django, você também vai aprender Banco de Dados, SQL, HTML, CSS, Javascript, Bootstrap e muito mais!

Quero aprender Python e Django de Verdade! Quero aprender!
Suporte

Tire suas dúvidas diretamente com o professor

Projetos práticos

Projetos práticos voltados para o mercado de trabalho

Prática profissional

Formação moderna com foco na prática profissional

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 =, pass ou raise).
  • valor or padrao não é a mesma coisa: ele descarta 0 e "".
  • 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! :rocket:

Vá Direto ao Assunto…

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? :thumbsup:

Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?

Sua assinatura não pôde ser validada.
Você fez sua assinatura com sucesso.

Assine as PyDicas e receba 30 dias do melhor conteúdo Python na sua Caixa de Entrada: direto e sem enrolação!

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 do for: transforma todos os itens.
  • if sozinho depois do for: filtra itens (e não aceita else).
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 y por x or y), use o pyproject.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 or descarta 0 e "", e is not None resolve.
  • Que cond and a or b e (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! :wink:

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.

Começe agora sua Jornada na Programação!

Não deixe para amanhã o sucesso que você pode começar a construir hoje!

#newsletter Olá :wave: Curtiu o artigo? Então faça parte da nossa Newsletter! Privacidade Não se preocupe, respeitamos sua privacidade. Você pode se descadastrar a qualquer momento.