
Passo 1 de 7
Converter não é o mesmo que validar
Diferencie a conversão de uma representação para inteiro da validação desse valor conforme as regras da aplicação.
Trilha de aprendizado · Nível 6 · Tutorial 2
Criar funções que rejeitam entradas inválidas com exceções adequadas e permitir que o código chamador decida como responder às falhas esperadas.
Converter não é o mesmo que validar
Diferencie a conversão de uma representação para inteiro da validação desse valor conforme as regras da aplicação. 2 min
Sinalizar uma entrada inválida com raise
Use raise para interromper uma função quando uma entrada viola seu contrato, escolhendo a exceção e a mensagem adequadas. 3 min
Verificar tipos sem aceitar bool por engano
Use isinstance para verificar os tipos exigidos pelo contrato e rejeitar booleanos quando uma quantidade precisa ser um inteiro real da aplicação. 2 min
Validar campos obrigatórios e limites
Organize as verificações de um dicionário para distinguir campos ausentes, tipos inadequados, textos em branco e quantidades fora da faixa permitida. 3 min
Validar antes de alterar os dados
Organize a função para validar e preparar a solicitação antes de modificar a lista de destino. 2 min
Deixar o chamador decidir como responder
Separe conversão, validação e resposta ao usuário para que cada falha seja tratada no lugar adequado. 2 min
Aplicação final: registrar somente solicitações válidas
Integre validação, sinalização com exceções e tratamento seletivo em um script local autocontido. 4 min

Passo 1 de 7
Diferencie a conversão de uma representação para inteiro da validação desse valor conforme as regras da aplicação.
Ao receber uma entrada, há duas perguntas separadas:
Neste tutorial, uma solicitação é válida quando o material está preenchido e a quantidade é um número inteiro entre 1 e 20, incluindo os limites.
Por isso, conseguir executar int(texto) não basta para aceitar a quantidade.
A quantidade passa primeiro pela conversão e, somente se ela funcionar, pela validação da faixa. Depois, os demais dados também precisam respeitar o contrato antes do registro.

Converter responde “isso pode virar um inteiro?”; validar responde “esse inteiro é permitido?”.
Exemplo
Considere estes textos recebidos para a quantidade:
"dez": não pode ser convertido com int; é uma falha de conversão."0": pode ser convertido no inteiro 0, mas viola a faixa de 1 a 20; é uma falha de validação."12": pode ser convertido no inteiro 12 e está na faixa permitida; a quantidade é válida.A última situação ainda exige que o material esteja preenchido para que a solicitação inteira seja válida.
Dica
O fluxo conceitual é: receber os textos → converter a quantidade → validar material e quantidade → registrar a solicitação. Uma etapa bem-sucedida não garante o sucesso das seguintes.
Associe cada entrada de quantidade ao resultado correto, considerando a faixa permitida de 1 a 20.
Toque em um item e depois no par correspondente.

Passo 2 de 7
Use raise para interromper uma função quando uma entrada viola seu contrato, escolhendo a exceção e a mensagem adequadas.
Dentro de uma função, uma condição pode reconhecer uma entrada inválida e usar raise para lançar uma exceção:
raise ValueError("quantidade deve estar entre 1 e 20")
ValueError(...) cria a exceção com uma mensagem, e raise a sinaliza. Nesse caminho, a execução da função é interrompida imediatamente. Se a própria função não tratar a exceção, ela segue para o código chamador.
Se a quantidade estiver fora da faixa, a confirmação e o retorno não serão executados.
def verificar_quantidade(quantidade):
if quantidade < 1 or quantidade > 20:
raise ValueError(
"quantidade deve estar entre 1 e 20"
)
print("Quantidade aceita")
return quantidadeA entrada válida continua pela função. A inválida encontra raise, interrompe esse caminho e envia a exceção ao chamador.

Depois de raise, as instruções restantes daquele caminho não são executadas.
Use TypeError quando o argumento tem um tipo incompatível com o contrato. Use ValueError quando o tipo é aceito, mas o valor viola uma regra.
TypeError.0 quando a faixa permitida é de 1 a 20: ValueError.Uma mensagem útil nomeia o argumento ou campo e informa a restrição violada. Compare "valor inválido" com "quantidade deve estar entre 1 e 20": a segunda orienta diretamente a correção.
Exemplo
raise TypeError("material deve ser uma string")
raise ValueError("material não pode ficar em branco")As duas falhas envolvem material, mas representam violações diferentes: tipo inadequado e valor inadequado.
Atenção
print("entrada inválida") apenas exibe um aviso e deixa o fluxo continuar. Retornar None, 0 ou outro valor aparentemente normal também pode esconder a falha. raise interrompe o caminho inválido e permite que o chamador decida como responder.
A função já recebeu a quantidade inteira 0, mas só aceita valores de 1 a 20. Complete:
raise ________("quantidade deve estar entre 1 e 20")
Uma função exige que material seja uma string. Ela detectou que o argumento tem um tipo inadequado antes de executar print("Solicitação registrada").
Escreva a instrução raise com uma mensagem útil. Depois, diga se a confirmação será executada e o que acontece com a exceção quando a função não a trata.
Escreva pelo menos 50 caracteres (0/50).

Passo 3 de 7
Use isinstance para verificar os tipos exigidos pelo contrato e rejeitar booleanos quando uma quantidade precisa ser um inteiro real da aplicação.
Antes de aplicar operações próprias de um tipo, confirme que o valor recebido é compatível. isinstance(valor, tipo) verifica isso para tipos embutidos como dict, str e int.
Se o tipo estiver incorreto, use TypeError e identifique na mensagem qual argumento ou campo violou o contrato.
Neste trecho, consideramos que as duas chaves já estão presentes; a validação de campos obrigatórios será organizada no próximo step.
def verificar_tipos(dados):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
# A verificação completa da quantidade vem a seguir.Dica
Só use operações de string no material depois de confirmar que ele é str. Da mesma forma, verifique o tipo da quantidade antes de realizar cálculos com ela.
Em Python, isinstance(True, int) e isinstance(False, int) resultam em True. Portanto, verificar apenas isinstance(quantidade, int) aceitaria booleanos.
Para o contrato da solicitação, isso não faz sentido: True e False não representam quantidades. A condição precisa rejeitar bool explicitamente.

Embora os booleanos estejam dentro do conjunto reconhecido por isinstance(valor, int), o contrato da aplicação os exclui das quantidades válidas.
A primeira parte rejeita booleanos; a segunda rejeita todos os demais valores que não são inteiros.
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um inteiro, sem aceitar booleanos")Atenção
O valor "5" deve ser rejeitado por essa função, pois é str, não int. A conversão do texto recebido do usuário fica a cargo do código de interação; a função que exige uma quantidade inteira não precisa aceitar nem converter texto numérico.
Qual condição executa o processamento somente quando quantidade é um inteiro e não é um booleano?

Passo 4 de 7
Organize as verificações de um dicionário para distinguir campos ausentes, tipos inadequados, textos em branco e quantidades fora da faixa permitida.
A solicitação segue um contrato: deve ser um dicionário com os campos material e quantidade. Valide do geral para o específico:
dados é um dicionário;material;quantidade.Essa ordem evita consultar chaves ou executar operações antes de saber se elas são permitidas. Cada raise interrompe a função na primeira violação encontrada.

Cada etapa só é alcançada quando a anterior foi satisfeita.
A ausência de uma chave é um ValueError: o dicionário existe, mas não cumpre o contrato. Essa verificação deve acontecer antes de dados["material"] ou dados["quantidade"].
Depois, use TypeError para tipos não aceitos e ValueError para conteúdos ou limites inválidos. Na quantidade, rejeite bool explicitamente, pois isinstance(True, int) resulta em True.
def validar_solicitacao(dados):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
if "material" not in dados:
raise ValueError("campo obrigatório ausente: material")
if "quantidade" not in dados:
raise ValueError("campo obrigatório ausente: quantidade")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
if material.strip() == "":
raise ValueError("material não pode ficar em branco")
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um número inteiro")
if not 1 <= quantidade <= 20:
raise ValueError("quantidade deve estar entre 1 e 20")Uma condição genérica como if not dados.get("campo") mistura problemas diferentes. As regras do contrato precisam distingui-los:
material igual a " ": o tipo está correto, mas falta conteúdo após strip();material igual a None: o tipo está incorreto;quantidade igual a 0: é um inteiro, mas está fora da faixa;quantidade igual a True: é rejeitada como tipo inadequado para uma quantidade.Ao separar as condições, a mensagem identifica o campo e a restrição realmente violada.
Exemplo
Em {"material": None, "quantidade": 0}, a função lança primeiro TypeError: material deve ser uma string. A quantidade ainda não é examinada. Se o material for corrigido, a próxima chamada poderá revelar ValueError: quantidade deve estar entre 1 e 20.
Organize as etapas na ordem segura para validar uma solicitação.

Passo 5 de 7
Organize a função para validar e preparar a solicitação antes de modificar a lista de destino.
Uma função de registro deve primeiro examinar a entrada, depois preparar um novo registro válido e somente então alterar a lista de destino.
Se uma verificação acionar raise, a execução é interrompida, mas alterações já realizadas não são desfeitas. Por isso, adicionar algo à lista antes do fim da validação pode deixar um registro inválido nela.
O caminho inválido precisa terminar antes da operação que modifica a coleção.

A lista só é alterada no último estágio, depois de todas as verificações.
Neste trecho, append acontece antes das verificações de preenchimento e faixa:
def registrar_solicitacao(solicitacoes, dados):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
if "material" not in dados:
raise ValueError("campo material é obrigatório")
if "quantidade" not in dados:
raise ValueError("campo quantidade é obrigatório")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um inteiro")
registro = {"material": material.strip(), "quantidade": quantidade}
solicitacoes.append(registro) # alteração prematura
if registro["material"] == "":
raise ValueError("material não pode ficar em branco")
if not 1 <= quantidade <= 20:
raise ValueError("quantidade deve estar entre 1 e 20")Exemplo
Considere uma lista inicialmente vazia e uma chamada com {"material": "Papel", "quantidade": 30}. O registro é adicionado e só depois a faixa é verificada. A função lança ValueError, mas a lista já contém {"material": "Papel", "quantidade": 30}.
A falha foi sinalizada corretamente, porém o estado da lista ficou incorreto.
Todas as condições que podem rejeitar a entrada aparecem antes de append. Um novo dicionário é preparado sem modificar dados.
def registrar_solicitacao(solicitacoes, dados):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
if "material" not in dados:
raise ValueError("campo material é obrigatório")
if "quantidade" not in dados:
raise ValueError("campo quantidade é obrigatório")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
if material.strip() == "":
raise ValueError("material não pode ficar em branco")
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um inteiro")
if not 1 <= quantidade <= 20:
raise ValueError("quantidade deve estar entre 1 e 20")
novo_registro = {
"material": material.strip(),
"quantidade": quantidade,
}
solicitacoes.append(novo_registro)Dica
Se uma chamada for rejeitada, a lista depois da chamada deve ter o mesmo conteúdo que tinha antes. Validar primeiro reduz efeitos parciais; raise, por si só, não oferece desfazimento automático.
No código com problema, identifique a linha que altera a lista cedo demais. Explique para onde ela deve ser movida e por que uma chamada rejeitada deve deixar a lista de destino inalterada.
Escreva pelo menos 80 caracteres (0/80).

Passo 6 de 7
Separe conversão, validação e resposta ao usuário para que cada falha seja tratada no lugar adequado.
A função registrar_solicitacao deve receber dados já estruturados, validar o contrato e adicionar somente registros válidos. Ela não precisa usar input nem imprimir mensagens de atendimento.
O código chamador recebe os textos do usuário, converte a quantidade e decide o que mostrar. Assim, uma falha de conversão fica separada de um valor convertido que foi rejeitado pela função.

O chamador controla a interação; a função controla as regras do registro.
Execute este script localmente. Observe que cada try envolve apenas a operação cuja falha esperada será tratada.
def registrar_solicitacao(solicitacoes, dados):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
if "material" not in dados:
raise ValueError("campo material é obrigatório")
if "quantidade" not in dados:
raise ValueError("campo quantidade é obrigatório")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
if not material.strip():
raise ValueError("material não pode ficar em branco")
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um número inteiro")
if not 1 <= quantidade <= 20:
raise ValueError("quantidade deve estar entre 1 e 20")
registro = {
"material": material.strip(),
"quantidade": quantidade,
}
solicitacoes.append(registro)
solicitacoes = []
material_texto = input("Material: ")
quantidade_texto = input("Quantidade: ")
try:
quantidade = int(quantidade_texto)
except ValueError:
print("Digite a quantidade usando um número inteiro.")
else:
dados = {
"material": material_texto,
"quantidade": quantidade,
}
try:
registrar_solicitacao(solicitacoes, dados)
except ValueError as erro:
print(f"Solicitação rejeitada: {erro}")
else:
print("Solicitação registrada com sucesso.")
print(solicitacoes)Dica
O primeiro try trata somente a conversão do texto para int. O segundo trata ValueError gerado pelas regras de validade, como material em branco ou quantidade fora da faixa. A confirmação aparece apenas no else da operação de registro, quando nenhuma exceção ocorreu.
Atenção
Nesse fluxo, input produz uma string e int produz um inteiro. Portanto, se o próprio programa chamar registrar_solicitacao com uma lista, None ou True no lugar esperado, o TypeError pode indicar uso incorreto da função pelo código.
Capturá-lo junto com toda entrada inválida e mostrar “corrija o que digitou” esconderia a origem real do defeito. Da mesma forma, uma captura indiscriminada não deve substituir falhas por zero, None ou uma falsa confirmação de sucesso.
Qual organização preserva melhor a separação entre a função de registro e o código chamador?

Passo 7 de 7
Integre validação, sinalização com exceções e tratamento seletivo em um script local autocontido.
A função receberá um dicionário com os campos obrigatórios material e quantidade. O material deve ser uma str preenchida após strip(). A quantidade deve ser um int de 1 a 20, inclusive, sem aceitar bool.
A ordem importa: primeiro a função examina todos os dados e prepara um novo registro. Somente depois adiciona esse registro à lista. Se alguma regra falhar, raise interrompe o caminho antes da alteração.
Observe que apenas o caminho aprovado alcança a coleção. A falha volta ao chamador como exceção, sem desfazer alterações anteriores — por isso a lista só deve ser modificada no final.

Validar primeiro evita que uma solicitação rejeitada seja adicionada parcialmente.
Crie um arquivo local com este conteúdo completo e execute-o com Python 3. As chamadas ao final verificam casos válidos, inválidos e a separação entre conversão e validação.
solicitacoes = []
def registrar_solicitacao(dados, destino):
if not isinstance(dados, dict):
raise TypeError("dados deve ser um dicionário")
if "material" not in dados:
raise ValueError("campo material é obrigatório")
if "quantidade" not in dados:
raise ValueError("campo quantidade é obrigatório")
material = dados["material"]
quantidade = dados["quantidade"]
if not isinstance(material, str):
raise TypeError("material deve ser uma string")
if not material.strip():
raise ValueError("material não pode ficar em branco")
if isinstance(quantidade, bool) or not isinstance(quantidade, int):
raise TypeError("quantidade deve ser um inteiro, sem aceitar booleanos")
if not 1 <= quantidade <= 20:
raise ValueError("quantidade deve estar entre 1 e 20")
registro = {
"material": material.strip(),
"quantidade": quantidade,
}
destino.append(registro)
return registro
def verificar(caso, dados):
estado_anterior = list(solicitacoes)
print(f"\n{caso}")
try:
registro = registrar_solicitacao(dados, solicitacoes)
except (TypeError, ValueError) as erro:
print(f"{type(erro).__name__}: {erro}")
print("Lista preservada:", solicitacoes == estado_anterior)
else:
print("Registrada:", registro)
def processar_entrada(material_texto, quantidade_texto):
print(f"\nInteração: {material_texto!r}, {quantidade_texto!r}")
try:
quantidade = int(quantidade_texto)
except ValueError:
print("Entrada rejeitada: quantidade precisa representar um inteiro.")
return
dados = {
"material": material_texto,
"quantidade": quantidade,
}
try:
registro = registrar_solicitacao(dados, solicitacoes)
except ValueError as erro:
print(f"Solicitação rejeitada: {erro}")
else:
print(f"Solicitação confirmada: {registro}")
verificar("Limite inferior", {"material": "Papel", "quantidade": 1})
verificar("Limite superior", {"material": "Caneta", "quantidade": 20})
verificar("Abaixo do limite", {"material": "Papel", "quantidade": 0})
verificar("Acima do limite", {"material": "Papel", "quantidade": 21})
verificar("Campo ausente", {"material": "Papel"})
verificar("Material em branco", {"material": " ", "quantidade": 3})
verificar("Material com tipo inadequado", {"material": None, "quantidade": 3})
verificar("Quantidade textual", {"material": "Papel", "quantidade": "3"})
verificar("Quantidade booleana", {"material": "Papel", "quantidade": True})
verificar("Dados com tipo inadequado", ["Papel", 3])
processar_entrada("Clipes", "doze")
processar_entrada("Clipes", "0")
processar_entrada("Clipes", "4")
print("\nLista final:", solicitacoes)
Confirme estes resultados:
1 e 20 são aceitas.0 e 21 geram ValueError.ValueError.TypeError.Lista preservada: True."doze" falha durante int(), enquanto "0" é convertido e depois rejeitado pela regra de validade.O TypeError da função não é capturado em processar_entrada: nesse fluxo, a interação constrói os tipos esperados. Se o próprio programa violar esse contrato, a falha deve continuar visível.
Execute o script no seu computador e explique por que "doze", "0" e True falham em etapas ou por motivos diferentes. Informe também como a saída comprova que a lista permanece inalterada quando uma validação falha.
Escreva pelo menos 180 caracteres (0/180).
Resumo
O programa fica mais previsível quando cada parte assume uma responsabilidade clara.
TypeError indica um tipo incompatível com o contrato; ValueError indica um valor inválido de um tipo aceito.Parabéns! Você concluiu: Validar entradas e sinalizar falhas com raise
100 XP
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks