1
resposta

Faça como eu fiz: gerador de funções personalizadas

Miguel está desenvolvendo um sistema de cupons de desconto e precisa de uma forma para aplicar diferentes taxas de desconto sobre os valores das compras. Diante deste problema, crie uma closure que gere uma função capaz de calcular o preço final com um desconto fixo definido pelo usuário.

Exemplo de entrada:

Digite a porcentagem de desconto: 10 

Digite o valor da compra: 200 
def criar_desconto(taxa):
    def aplicar_desconto(codigo, produtos):
        if codigo in produtos:
            produto = produtos[codigo]["nome"]
            preco = produtos[codigo]["preco"]
            valor_desconto = preco * taxa
            preco_final = preco - valor_desconto
            print(f'Código: {codigo}')
            print(f'Produto: {produto}')
            print(f'Valor original: R$ {preco:.2f}')
            print(f'Desconto aplicado: R$ {valor_desconto:.2f}')
            print(f'Valor final: R$ {preco_final:.2f}')
            return preco_final
        else:
            print("Código inválido. Produto não encontrado.")
            return 0
    return aplicar_desconto



produtos = {
    "001": {"nome": "Camisa de seda preta de mangas longas", "preco": 100},
    "002": {"nome": "Minissaia xadrez", "preco": 200},
    "003": {"nome": "Calça de sarja caqui", "preco": 150},
    "004": {"nome": "Blazer azul marinho", "preco": 350}
}


desconto_10 = criar_desconto(0.10)
desconto_25 = criar_desconto(0.25)


total = 0
while True:
    codigo = input("Digite o código do produto (ou 'fim' para encerrar): ")
    if codigo.lower() == "fim":
        break
    
    if codigo in produtos:
        preco = produtos[codigo]["preco"]
      
        if preco >= 200:
            total += desconto_25(codigo, produtos)
        else:
            total += desconto_10(codigo, produtos)
    else:
        print("Código inválido. Tente novamente.")

print("==============================")
print(f'Valor total da compra: R$ {total:.2f}')
print("==============================")

Digite o código do produto (ou 'fim' para encerrar): 001
Código: 001
Produto: Camisa de seda preta de mangas longas
Valor original: R$ 100.00
Desconto aplicado: R$ 10.00
Valor final: R$ 90.00
Digite o código do produto (ou 'fim' para encerrar): 004
Código: 004
Produto: Blazer azul marinho
Valor original: R$ 350.00
Desconto aplicado: R$ 87.50
Valor final: R$ 262.50
Digite o código do produto (ou 'fim' para encerrar): fim

==============================
Valor total da compra: R$ 352.50
==============================
1 resposta

Olá, Andressa. Como vai?

Parabéns pela resolução do desafio! O seu código ficou excelente e demonstra que você compreendeu muito bem o conceito de closures em Python.

A forma como você utilizou a função interna aplicar_desconto para memorizar o escopo da função externa criar_desconto (guardando a variável taxa) está correta. Além disso, a lógica que você implementou para criar dinamicamente os objetos desconto_10 e desconto_25 e aplicá-los com base no valor do produto ficou muito interessante e prática.

Para agregar ainda mais valor ao seu aprendizado, trago uma sugestão de boa prática baseada em um conceito chamado Princípio da Responsabilidade Única.

No seu código atual, a função aplicar_desconto faz três coisas: calcula o preço, exibe as mensagens na tela (print) e busca os dados dentro do dicionário de produtos. Em projetos reais, costumamos separar a lógica de cálculo da lógica de exibição. Isso torna o código mais flexível. Se amanhã você precisar calcular o desconto para um carrinho de compras inteiro (sem exibir os prints um por um), uma função focada apenas no cálculo ajudaria muito.

Veja como poderíamos refatorar a estrutura da sua closure para torná-la ainda mais reutilizável:

def criar_desconto(porcentagem):
    # A função interna foca apenas em receber um valor e calcular o desconto
    def aplicar_desconto(valor_original):
        valor_desconto = valor_original * (porcentagem / 100)
        return valor_original - valor_desconto
    return aplicar_desconto

Com essa estrutura mais simples e focada, você pode aplicar o desconto em qualquer parte do sistema, independentemente de os dados estarem em um dicionário, banco de dados ou virem de uma API. Na hora de usar no seu laço principal, você faria a busca do produto primeiro e passaria apenas o preço para a função:

# Criando os geradores de desconto passando a porcentagem direta (ex: 10 para 10%)
desconto_10 = criar_desconto(10)
desconto_25 = criar_desconto(25)

# Dentro do seu loop, após validar o produto:
preco_original = produtos[codigo]["preco"]

if preco_original >= 200:
    preco_final = desconto_25(preco_original)
else:
    preco_final = desconto_10(preco_original)

Dessa forma, os prints de exibição ficariam no bloco principal do programa, mantendo suas funções limpas e focadas apenas em processar os cálculos.

Continue praticando e compartilhando suas soluções aqui no fórum!

Espero que possa ter lhe ajudado!