Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Faça como eu fiz: calculadora com lambda

def calculadora(num1, num2, operador):
    operacoes = {
      '+': lambda x, y: x + y,
      '-': lambda x, y: x - y,
      '*': lambda x, y: x * y,
      '/': lambda x, y: x / y
    }
    if operador not in operacoes:
      raise ValueError('Operador inválido')

    if not isinstance(num1, float) or not isinstance(num2, float):
      raise ValueError('informe números somente')
      
    if operador == '/' and num2 == 0:
      raise ZeroDivisionError('Não é possível dividir por zero')

    return operacoes[operador](num1, num2)

while True:
  try:
    num1 = float(input('Digite o primeiro número: '))
    num2 = float(input('Digite o segundo número: '))
    operador = input('Escolha a operação (+, -, *, /): ')
    
    resultado = calculadora(num1, num2, operador)
    print(f'O Resultado é: {resultado}')
    break
    
  except ValueError as e:
    print(f'Erro de valor: {e}')
  except ZeroDivisionError as e:
    print(f'Erro matemático: {e}')
  except Exception as e:
    print(f'Ocorreu um erro inesperado: {e}')
2 respostas
solução!

Olá, Marcelo. Como vai?

Excelente projeto! A sua solução para a calculadora ficou fantástica e demonstra um entendimento muito maduro de várias ferramentas poderosas do Python: o uso de um dicionário como estrutura de controle (substituindo múltiplos if/elif), o tratamento robusto de exceções com blocos try/except específicos e, claro, o uso de funções anônimas com lambda.

Associar os operadores (+, -, *, /) diretamente a expressões lambda dentro de um dicionário é uma prática de mercado elegantíssima, que torna o código escalável e de fácil manutenção.

Para agregar ainda mais valor ao seu aprendizado, vale a pena analisarmos uma pequena inconsistência na validação de tipos do seu código e como podemos deixar sua calculadora ainda mais flexível.

Ajuste na validação de tipos (isinstance)

Na linha onde você faz a seguinte checagem:

if not isinstance(num1, float) or not isinstance(num2, float):

O programa verifica se os números são estritamente do tipo float. No entanto, no bloco while, você já converte as entradas do usuário usando float(input(...)). Isso significa que num1 e num2 sempre serão do tipo float ao entrarem na função, tornando essa checagem redundante.

Além disso, se no futuro você decidisse passar números inteiros diretamente para a função calculadora(5, 3, '+'), a função dispararia o erro de ValueError('informe números somente'), porque o número 5 é um int, e não um float.

Uma boa prática em Python para permitir tanto inteiros quanto decimais é passar uma tupla de tipos aceitos para o isinstance():

# Aceita tanto int (inteiros) quanto float (decimais)
if not isinstance(num1, (int, float)) or not isinstance(num2, (int, float)):
    raise ValueError('informe números somente')

Expandindo o projeto: Operações com apenas um número

As funções lambda são ótimas pela sua flexibilidade. Mas o que aconteceria se você quisesse adicionar uma operação que precisa de apenas um número, como elevar um número ao quadrado ou calcular a raiz quadrada?

Para que o seu dicionário de funções lambda aceite operações com números diferentes de argumentos, você pode definir os parâmetros com valores padrão. Veja que extensão interessante para o seu projeto:

def calculadora(num1, num2, operador):
    operacoes = {
        '+': lambda x, y: x + y,
        '-': lambda x, y: x - y,
        '*': lambda x, y: x * y,
        '/': lambda x, y: x / y,
        '²': lambda x, y=None: x ** 2  # y recebe None por padrão se não for enviado
    }
    
    if operador not in operacoes:
        raise ValueError('Operador inválido')
        
    if operador == '/' and num2 == 0:
        raise ZeroDivisionError('Não é possível dividir por zero')

    # Se for a operação de elevar ao quadrado, passamos apenas o num1
    if operador == '²':
        return operacoes[operador](num1)
        
    return operacoes[operador](num1, num2)

Seu código principal está muito bem escrito, especialmente a captura das mensagens de erro customizadas com as e no print. Continue aplicando essas boas práticas de tratamento de erros e estruturas funcionais!

Espero que possa ter lhe ajudado!

Grato Evandro, não tinha pensando sobre operações de um operando