3
respostas

[Projeto] Desafio: Hora da prática

Desafio: hora da prática

def divisao(a, b) -> float:
if b == 0:
raise ValueError("Não é possível dividir por zero")
return a / b

try:
valor1 = float(input("Digite o primeiro valor: "))
valor2 = float(input("Digite o segundo valor: "))
resultado = divisao(valor1, valor2)
except ValueError as e:
print(f"Erro: {e}. Certifique-se de digitar números válidos.")
except Exception as e:
print(f"Ocorreu um erro inesperado: {e}")
else:
print(f"Resultado da divisão: {resultado}")
finally:
print("Divisão concluída")

idades = {'Júlia': 16, 'Carol': 23, 'Alberto': 19, 'Roberta': 17}

def mostrar_idade(nome):
if nome in idades:
return idades[nome]
else:
raise KeyError("Nome não encontrado")

nome = input("Digite um nome: ")
try:
idade = mostrar_idade(nome)
except KeyError as e:
print(f"Erro: {e}")
else:
print(f"A idade de {nome} é {idade}.")
finally:
print("Programa finalizado.")

  1. def floater(lista) -> list:
    try:
    lista_real = []
    for element in lista:
    lista_real.append(float(element))
    except ValueError:
    print("Erro: Há um ou mais números inválidos na lista.")
    return None
    except TypeError:
    print("Erro: Há um ou mais elementos não numéricos na lista.")
    return None
    except Exception as e:
    print(f"Erro inesperado: {e}")
    return None
    else:
    return lista_real
    finally:
    print("Fim da execução da função")

lista_exemplo = [1, 3, 10, 25, {}, 40]

lista_real = floater(lista_exemplo)

if lista_real is not None:
print(f"Lista convertida: {lista_real}")
else:
print("A conversão da lista falhou.")

  1. def agrupar(lista1, lista2) -> tuple:
    try:
    length = max(len(lista1), len(lista2))
    tupla_nova = tuple((lista1[i], lista2[i], lista1[i] + lista2[i]) for i in range(length))
    except ValueError:
    print("Erro: Um ou mais elementos nas listas não podem ser somados ou convertidos.")
    return None
    except IndexError:
    print("Erro: Há uma disparidade no tamanho das listas para a operação de agrupamento.")
    return None
    except TypeError:
    print("Erro: Há um ou mais elementos nas listas com tipos incompatíveis para as operações (ex: dicionários, conjuntos, letras).")
    return None
    except Exception as e:
    print(f"Erro inesperado: {e}")
    return None
    else:
    return tupla_nova
    finally:
    print("Fim da execução da função agrupar.")

lista1 = [4,6,7,9,10]
lista2 = [-4,6,8,7,9]
print("\n--- Primeira chamada da função ---")
resultado1 = agrupar(lista1, lista2)
if resultado1 is not None:
print(f"Resultado da primeira chamada: {resultado1}")

lista1 = [4,6,7,9,10,4] # Nova lista1 com tamanho diferente
lista2 = [-4,6,8,7,9]
print("\n--- Segunda chamada da função ---")
resultado2 = agrupar(lista1, lista2)
if resultado2 is not None:
print(f"Resultado da segunda chamada: {resultado2}")

lista1 = [4,6,7,9,'A']
lista2 = [-4,'E',8,7,9]
print("\n--- Terceira chamada da função ---")
resultado3 = agrupar(lista1, lista2)
if resultado2 is not None:
print(f"Resultado da terceira chamada: {resultado3}")

3 respostas
  1. def verificar_questao(resposta: str, gabarito_questao: str) -> bool:
    """
    Verifica se a resposta de uma questão está correta.
    """
    return resposta == gabarito_questao

def avaliar_testes_alunos(respostas_alunos: list[list[str]], gabarito: list[str]) -> list[int]:
"""
Avalia os testes dos alunos, verificando a validade das alternativas
e calculando as notas.

Args:
respostas_alunos: Uma lista de listas, onde cada sublista contém
as respostas de um aluno para as questões.
gabarito: Uma lista com as respostas corretas das questões.

Returns:
Uma lista de inteiros, onde cada inteiro é a nota de um aluno.

Raises:
ValueError: Se alguma alternativa fornecida por um aluno não for 'A', 'B', 'C' ou 'D'.
IndexError: Se o número de respostas de um aluno for diferente do número de questões no gabarito.
"""
alternativas_validas = ['A', 'B', 'C', 'D']
notas_finais_alunos = []

for idx_aluno, respostas_aluno in enumerate(respostas_alunos):
# Validar a quantidade de respostas do aluno vs gabarito
if len(respostas_aluno) != len(gabarito):
raise IndexError(f"O aluno {idx_aluno + 1} possui {len(respostas_aluno)} respostas, mas o gabarito tem {len(gabarito)} questões.")

# Validar as alternativas de cada aluno
for alternativa in respostas_aluno:
  if alternativa not in alternativas_validas:
    raise ValueError(f"A alternativa '{alternativa}' não é uma opção de alternativa válida.")

# Se a validação passou, calcular a nota do aluno
acertos = 0
for i in range(len(gabarito)):
  if verificar_questao(respostas_aluno[i], gabarito[i]):
    acertos += 1
notas_finais_alunos.append(acertos)

return notas_finais_alunos

Gabarito e respostas fornecidas pelo usuário

gabarito = ['D', 'A', 'B', 'C', 'A']
testes_sem_ex = [['D', 'A', 'B', 'C', 'A'], ['C', 'A', 'A', 'C', 'A'], ['D', 'B', 'A', 'C', 'A']]
testes_com_ex = [['D', 'A', 'B', 'C', 'A'], ['C', 'A', 'A', 'E', 'A'], ['D', 'B', 'A', 'C', 'A']]

print("--- Teste com notas sem exceção ---")
try:
notas_sem_ex = avaliar_testes_alunos(testes_sem_ex, gabarito)
print(f"Notas dos alunos (sem exceção): {notas_sem_ex}")
except (ValueError, IndexError) as e:
print(f"Erro ao avaliar testes (sem exceção): {e}")
finally:
print("Fim da avaliação de testes sem exceção.\n")

print("--- Teste com notas com exceção ---")
try:
notas_com_ex = avaliar_testes_alunos(testes_com_ex, gabarito)
print(f"Notas dos alunos (com exceção): {notas_com_ex}")
except (ValueError, IndexError) as e:
print(f"Erro ao avaliar testes (com exceção): {e}")
finally:
print("Fim da avaliação de testes com exceção.")

#6

pontuacao = [',', '.', '!', '?',':', '-','=', '+', '/', '"', '(',')', '{', '}', '[', ']']

def tratar_palavra(palavras: list[str]) -> str:
for palavra in palavras:
if palavra in pontuacao:
palavra = palavra.replace(palavra, '')
return palavra

def avaliar_palavra(palavras: list[str]):
poluido:bool = False
for palavra in palavras:
for letra in palavra:
if letra in pontuacao:
print(f'Texto apresenta pontuação na palavra "{palavra}."')
poluted = True
if not poluido:
print("Texto já tratado.")

lista_tratada = ['Python', 'é', 'uma', 'linguagem', 'de', 'programação', 'poderosa', 'versátil',
'e', 'fácil', 'de', 'aprender', 'utilizada', 'em', 'diversos', 'campos', 'desde',
'análise', 'de', 'dados', 'até', 'inteligência', 'artificial']

lista_nao_tratada = ['Python', 'é', 'uma', 'linguagem', 'de', 'programação', 'poderosa,', 'versátil',
'e', 'fácil,', 'de', 'aprender', 'utilizada', 'em', 'diversos', 'campos,', 'desde',
'análise', 'de', 'dados', 'até', 'inteligência', 'artificial!']

avaliar_palavra(lista_tratada)
avaliar_palavra(lista_nao_tratada)

  1. def divide_colunas(pressao: list[float], temperatura: list[float]) -> list[float]:
    if(len(pressao) != len(temperatura)):
    raise IndexError("As listas de pressão e temperatura devem ter o mesmo tamanho.")

    resultados = []
    epsilon = 1e-9 # um valor bem pequeno para evitar divisão por 0. Para esse caso, vi que temperatura zero seria aceitável e, por isso considerei aproximar mais viável
    for p, t in zip(pressao, temperatura): # Usando o zip da dica para uma iteração mais limpa
    try:
    if t == 0:
    # Usando o epsilon para aproximar
    resultados.append(p / epsilon)
    else:
    resultados.append(p / t)
    except OverflowError:
    print(f"Aviso: Sobrecarva no índice {len(resultados)}. O resultado ficou indefinido.") # Use len(resultados) para o índice atual
    resultados.append(None)
    except TypeError:
    print(f"Aviso: Valor não numérico no índice {len(resultados)}.")
    resultados.append(float('nan'))
    return resultados

--- Exemplos de uso com tratamento de exceções na chamada ---

print("\n--- Teste 1: Dados sem exceção --- ")
pressoes_1 = [100.0, 120.0, 140.0, 160.0, 180.0]
temperaturas_1 = [20.0, 25.0, 30.0, 35.0, 40.0]
try:
resultado_1 = divide_colunas(pressoes_1, temperaturas_1)
print(f"Resultados: {resultado_1}")
except Exception as e:
print(f"Erro na chamada: {type(e).name} - {e}")
finally:
print("Fim do Teste 1.\n")

print("--- Teste 2: Exceção zero divisor (com aproximação) --- ")
pressoes_2 = [60.0, 120.0, 140.0, 160.0, 180.0]
temperaturas_2 = [0.0, 25.0, 30.0, 35.0, 40.0]
try:
resultado_2 = divide_colunas(pressoes_2, temperaturas_2)
print(f"Resultados: {resultado_2}")
except Exception as e:
print(f"Erro na chamada: {type(e).name} - {e}")
finally:
print("Fim do Teste 2.\n")

print("--- Teste 3: Exceção IndexError (tamanhos diferentes) --- ")
pressoes_3 = [100.0, 120.0, 140.0, 160.0]
temperaturas_3 = [20.0, 25.0, 30.0, 35.0, 40.0] # Diferente tamanho
try:
resultado_3 = divide_colunas(pressoes_3, temperaturas_3)
print(f"Resultados: {resultado_3}")
except Exception as e:
print(f"Erro na chamada: {type(e).name} - {e}")
finally:
print("Fim do Teste 3.\n")

Olá, Paulo. Como vai?

É excelente ver o nível de maturidade do seu código! Você não apenas resolveu os desafios, mas aplicou boas práticas de engenharia de software, como o uso de type hints (indicação de tipos como -> list), docstrings para documentação e uma estrutura muito sólida de tratamento de exceções.

Gostaria de destacar alguns pontos muito interessantes da sua implementação e oferecer sugestões para aprofundar ainda mais seus conhecimentos:

  • Estratégia de Epsilon: No exercício 7, sua decisão de usar um epsilon (1e-9) para evitar a divisão por zero é uma prática muito comum em computação científica e Data Science. Isso evita que o processamento de grandes volumes de dados seja interrompido por um único valor problemático, mantendo a estabilidade numérica do algoritmo.

  • Documentação e Clareza: O exercício 5 está exemplar. O uso de comentários estruturados (docstrings) facilita muito o trabalho em equipe, pois permite que outros desenvolvedores entendam rapidamente o que a função recebe e o que ela retorna, além de quais erros ela pode disparar.

  • Refatoração com List Comprehension: No exercício 3 (função floater), você utilizou um laço for tradicional com append. Em Python, podemos tornar isso mais conciso e performático usando List Comprehensions.

Veja uma sugestão de como o bloco try ficaria mais enxuto:

def floater(lista) -> list:
    try:
        # Tenta converter toda a lista de uma vez
        return [float(element) for element in lista]
    except (ValueError, TypeError) as e:
        print(f"Erro de conversão: {e}")
        return None
    finally:
        print("Fim da execução da função")
  • O método get em Dicionários: No exercício 2, você verificou a existência da chave com if nome in idades. Embora esteja correto, o Python oferece o método .get(), que permite buscar um valor e definir um retorno padrão caso a chave não exista, muitas vezes eliminando a necessidade de um try/except para casos simples:
# Se o nome não existir, retorna 0 ou qualquer valor padrão definido
idade = idades.get(nome, "Não localizado")
  • Tratamento de Strings (Exercício 6): Na sua função avaliar_palavra, você verificou a poluição caractere por caractere. Uma forma muito eficiente de lidar com isso em processamento de texto é usar o método .strip() com uma string de pontuações, ou até mesmo Expressões Regulares (RegEx) para limpezas mais complexas.

Seu progresso com as cláusulas else e finally demonstra que você compreendeu bem o fluxo de execução do Python. O else é ótimo para garantir que o código de sucesso só rode se nada falhar, e o finally é indispensável para fechar conexões ou liberar recursos.

Espero que possa ter lhe ajudado!