Olá, Alex. Como vai?
Sensacional ver você alcançando o arquivo Alura ex036.py! Olhando a estrutura do seu código, fica claro que você já cruzou a linha de programador iniciante e está construindo arquiteturas de código muito elegantes e maduras.
O design dessa calculadora ficou sensacional. Em vez de usar aquela estrutura clássica e gigantesca cheia de if / elif / else para cada operação, você utilizou um dicionário de funções lambda (que aparece parcialmente mapeado no topo). Essa técnica é conhecida no mercado como o padrão de projeto Command ou tabelas de despacho (dispatch tables). Você mapeia o símbolo do operador (a chave) diretamente para a expressão lógica que deve ser executada (o valor). É um código extremamente limpo, rápido e profissional!
Também achei excelente a sua validação na linha 6 para evitar o clássico erro de divisão por zero, além do tratamento na linha 20 com .is_integer() para limpar os números decimais desnecessários e exibir 600 em vez de 600.0 no terminal. O resultado ficou impecável!
Para expandir ainda mais o seu conhecimento sobre essa estrutura de dicionários com funções, quero compartilhar duas dicas técnicas muito valiosas:
.get()Na sua linha 15, você fez uma validação usando o operador in: if operacao in calculadora:. Essa abordagem está 100% correta.
Contudo, os dicionários em Python possuem um método nativo chamado .get() que foi desenhado exatamente para buscar uma chave com segurança. Se a chave existir, ele traz o valor; se não existir, ele retorna None (ou um valor padrão que você escolher), sem quebrar o programa.
Veja como você poderia unificar o teste de existência e a execução em um bloco ainda mais enxuto:
# Tenta buscar a função lambda correspondente no dicionário
funcao_operacao = calculadora.get(operacao)
if funcao_operacao:
# Se encontrou a operação, executa passando os números
resultado = funcao_operacao(num1, num2)
# (Seu bloco de formatação visual do resultado continua aqui...)
else:
print("Operação inválida.")
Na linha 6 do seu código, você colocou uma proteção maravilhosa: if y != 0 else "Erro (divisão por zero)".
Essa blindagem impede que o Python lance uma exceção e trave o script. Porém, fique atento a um detalhe do fluxo: se o usuário tentar dividir por zero, a sua variável resultado passará a guardar uma string (o texto "Erro (divisão por zero)").
Logo em seguida, na linha 20, o seu código faz a seguinte checagem:
if isinstance(resultado, float) and resultado.is_integer():
Como "Erro (divisão por zero)" é um texto (string) e não um float, o Python simplesmente pulará esse bloco if com segurança e imprimirá na tela: O resultado é: Erro (divisão por zero). O programa não vai quebrar, o que é ótimo!
Porém, para seguir as melhores práticas estritas de desenvolvimento (onde funções matemáticas devem retornar idealmente números ou erros controlados), muitos programadores preferem que, em caso de erro matemático, a função retorne um valor especial do Python chamado None ou o próprio valor de indeterminação flutuante float('nan') (Not a Number).
Tratar o erro logo na exibição final impede que strings fiquem "passeando" por variáveis que deveriam ser puramente numéricas:
# Exemplo de tratamento na hora do print caso o resultado seja None
if resultado is None:
print("Não é possível realizar divisão por zero.")
else:
print(f"O resultado é: {resultado}")
Parabéns, Alex! Chegar ao exercício 36 com esse nível de sofisticação técnica, aplicando lambdas, dicionários estruturados e métodos de tipagem como isinstance é a prova do seu enorme progresso. Continue firme com essa consistência fantástica!
Espero que possa ter lhe ajudado!