Desafio Python

Sistema de saque com exceções personalizadas e finally

Enunciado

Implemente uma classe ContaBancaria com atributos titular e saldo. O método sacar(valor) deve lançar SaldoInsuficienteError (personalizada) se o valor for maior que o saldo, e ValueError se o valor for negativo. Use try/except/else/finally para: tentar o saque, capturar SaldoInsuficienteError e ValueError, imprimir mensagens apropriadas, e no finally imprimir "Operação finalizada". O programa deve testar três casos: saque válido, saque com saldo insuficiente e saque com valor negativo.

Requisitos

  • A classe ContaBancaria deve ter os atributos titular e saldo.
  • O método sacar deve lançar SaldoInsuficienteError se valor > saldo e ValueError se valor < 0.
  • O bloco try deve ter except para as duas exceções, um else para sucesso e um finally que imprime "Operação finalizada".
  • O programa deve executar os três cenários e imprimir as mensagens correspondentes.

Código inicial

class SaldoInsuficienteError(Exception):
    pass

class ContaBancaria:
    def __init__(self, titular, saldo):
        self.titular = titular
        self.saldo = saldo

    def sacar(self, valor):
        # seu código aqui
        pass

# Teste os três casos
conta = ContaBancaria("Ana", 100)

# Caso 1: saque válido
# Caso 2: saldo insuficiente
# Caso 3: valor negativo

Saída esperada

Saque de 50 realizado. Novo saldo: 50
Operação finalizada
Erro: Saldo insuficiente para sacar 200
Operação finalizada
Erro: Valor de saque não pode ser negativo
Operação finalizada
Ver dica

No método sacar, verifique valor < 0 primeiro e levante ValueError. Depois verifique valor > self.saldo e levante SaldoInsuficienteError. No try, chame conta.sacar(...) e trate as exceções.

Mostrar solução
class SaldoInsuficienteError(Exception):
    """Exceção lançada quando o saldo é insuficiente para um saque."""
    pass

class ContaBancaria:
    def __init__(self, titular, saldo):
        self.titular = titular
        self.saldo = saldo

    def sacar(self, valor):
        if valor < 0:
            raise ValueError("Valor de saque não pode ser negativo")
        if valor > self.saldo:
            raise SaldoInsuficienteError(f"Saldo insuficiente para sacar {valor}")
        self.saldo -= valor
        return self.saldo

conta = ContaBancaria("Ana", 100)

# Caso 1: saque válido
try:
    novo_saldo = conta.sacar(50)
except SaldoInsuficienteError as e:
    print(f"Erro: {e}")
except ValueError as e:
    print(f"Erro: {e}")
else:
    print(f"Saque de 50 realizado. Novo saldo: {novo_saldo}")
finally:
    print("Operação finalizada")

# Caso 2: saldo insuficiente
try:
    conta.sacar(200)
except SaldoInsuficienteError as e:
    print(f"Erro: {e}")
except ValueError as e:
    print(f"Erro: {e}")
else:
    print("Saque realizado com sucesso")
finally:
    print("Operação finalizada")

# Caso 3: valor negativo
try:
    conta.sacar(-10)
except SaldoInsuficienteError as e:
    print(f"Erro: {e}")
except ValueError as e:
    print(f"Erro: {e}")
else:
    print("Saque realizado com sucesso")
finally:
    print("Operação finalizada")

Passo a passo

  1. Definimos SaldoInsuficienteError herdando de Exception.
  2. A classe ContaBancaria tem __init__ que guarda titular e saldo.
  3. O método sacar verifica primeiro se valor < 0, lançando ValueError.
  4. Depois verifica se valor > self.saldo, lançando SaldoInsuficienteError.
  5. Se passar, subtrai do saldo e retorna o novo saldo.
  6. Para cada caso, usamos um bloco try que chama sacar.
  7. Os except capturam as exceções específicas e imprimem mensagens.
  8. O else executa se não houver exceção, imprimindo o sucesso.
  9. O finally sempre imprime "Operação finalizada".

Por que funciona

A ordem das verificações garante que valores negativos sejam rejeitados antes de checar saldo. O uso de exceções personalizadas torna o código expressivo. O finally assegura que a mensagem de finalização apareça independentemente do resultado, simulando um log de auditoria.

Erros comuns

  • Inverter a ordem das verificações: se checar saldo antes de valor negativo, um valor negativo pode passar se o saldo for alto o suficiente. Ex.: sacar(-10) com saldo 100 não lançaria erro se a verificação de saldo viesse primeiro.
  • Esquecer o finally: a mensagem não seria impressa em todos os casos.
  • Capturar Exception genérica: perderia a distinção entre os erros e as mensagens específicas.
  • Não atualizar o saldo: se esquecer self.saldo -= valor, o saque não teria efeito.

Outra forma de resolver

Poderia usar um único try com múltiplos except para os três casos, mas a repetição do bloco try deixa claro cada cenário. Uma alternativa é criar uma função auxiliar que executa o saque e trata as exceções, mas para fins didáticos a repetição é aceitável.

Saída esperada

Saque de 50 realizado. Novo saldo: 50
Operação finalizada
Erro: Saldo insuficiente para sacar 200
Operação finalizada
Erro: Valor de saque não pode ser negativo
Operação finalizada