1
resposta

[Sugestão] Mão na massa: refatorando uma função

item_cardapio.py

from abc import ABC, abstractmethod

class ItemCardapio(ABC):
    def __init__(self, nome, preco):
        self._nome = nome
        self._preco = preco

    @abstractmethod
    def aplicar_desconto(self):
        pass
    

bebida.py

from modelos.cardapio.item_cardapio import ItemCardapio
class Bebida(ItemCardapio):
    def __init__(self,nome,preco,tamanho):
        super().__init__(nome, preco)
        self.tamanho = tamanho
    
    def __str__(self):
        return self._nome
    
    def aplicar_desconto(self):
        self._preco -= (self._preco*0.08)

prato.py

from modelos.cardapio.item_cardapio import ItemCardapio

class Prato(ItemCardapio):
    def __init__(self, nome, preco, descricao):
        super().__init__(nome, preco)
        self.descricao = descricao

    def __str__(self):
        return self._nome
    
    def aplicar_desconto(self):
        self._preco -= (self._preco*0.05)

sobremesa.py

from modelos.cardapio.item_cardapio import ItemCardapio

class Sobremesa(ItemCardapio):
    def __init__(self, nome, preco, tipo, tamanho, descricao):
        super().__init__(nome, preco)
        self.tipo = tipo
        self.tamanho = tamanho
        self.descricao = descricao

    def __str__(self):
        return f'{super.__str__()} | Tipo: {self.tipo} | Tamanho: {self.tamanho} | Descrição: {self.descricao}'
    
    def aplicar_desconto(self):
        self._preco -= (self._preco * 0.1)
    

restaurante.py

from modelos.avaliacao import Avaliacao
from modelos.cardapio.item_cardapio import ItemCardapio

class Restaurante:
    restaurantes = []

    def __init__(self, nome, categoria):
        self._nome = nome.title()
        self._categoria = categoria.upper()
        self._ativo = False
        self._avaliacao = []
        self._cardapio = []
        Restaurante.restaurantes.append(self)
    
    def __str__(self):
        return f'{self._nome} | {self._categoria}'
    
    @classmethod
    def listar_restaurantes(cls):
        print(f'{'Nome do restaurante'.ljust(25)} | {'Categoria'.ljust(25)} | {'Avaliação'.ljust(25)} |{'Status'}')
        for restaurante in cls.restaurantes:
            print(f'{restaurante._nome.ljust(25)} | {restaurante._categoria.ljust(25)} | {str(restaurante.media_avaliacoes).ljust(25)} |{restaurante.ativo}')

    @property
    def ativo(self):
        return '⌧' if self._ativo else '☐'
    
    def alternar_estado(self):
        self._ativo = not self._ativo

    def receber_avaliacao(self, cliente, nota):
        if 0 < nota <= 5: 
            avaliacao = Avaliacao(cliente, nota)
            self._avaliacao.append(avaliacao)

    @property
    def media_avaliacoes(self):
        if not self._avaliacao:
            return '-'
        soma_das_notas = sum(avaliacao._nota for avaliacao in self._avaliacao)
        quantidade_de_notas = len(self._avaliacao)
        media = round(soma_das_notas / quantidade_de_notas, 1)
        return media

    def adicionar_no_cardapio(self, item):
        if isinstance(item, ItemCardapio):
            self._cardapio.append(item)

    @property
    def exibir_cardapio(self):
        print(f'Cardapio do restaurante {self._nome}\n')
        for i,item in enumerate(self._cardapio, start= 1):
            if hasattr(item, 'descricao') and not hasattr(item, 'tipo'):
                mensagem_prato = f'{i}. Nome: {item._nome} | Preço: R$:{item._preco} | Descrição: {item.descricao}'
                print(mensagem_prato)
            elif hasattr(item, 'tamanho') and not hasattr(item,'tipo'):
                mensagem_bebida = f'{i}. Nome: {item._nome} | Preço: R$:{item._preco} | Tamanho: {item.tamanho}'
                print(mensagem_bebida)
            else:
                mensagem_sobremesa = f'{i}. Nome: {item._nome} | Preço: R$:{item._preco} | Tamanho: {item.tamanho} | Tipo: {item.tipo} | Descrição: {item.descricao}'
                print(mensagem_sobremesa)


                

app.py

from modelos.restaurante import Restaurante
from modelos.cardapio.bebida import Bebida
from modelos.cardapio.prato import Prato
from modelos.cardapio.sobremesa import Sobremesa

restaurante_praca = Restaurante('praça', 'Gourmet')

bebida_suco = Bebida('Suco de Melancia', 5.0, 'Grande')
bebida_suco.aplicar_desconto()
prato_panzinho = Prato('Paozinho', 2.00, 'O melhor pão da cidade')
prato_panzinho.aplicar_desconto() 
sobremesa_sorvete = Sobremesa('Sorvete de morango',15.00,'Gelado', 'M', 'Sorvete de creme com pedaços de morango')
sobremesa_sorvete.aplicar_desconto()

restaurante_praca.adicionar_no_cardapio(bebida_suco)
restaurante_praca.adicionar_no_cardapio(prato_panzinho)
restaurante_praca.adicionar_no_cardapio(sobremesa_sorvete)



def main():
    restaurante_praca.exibir_cardapio
if __name__ == '__main__':
    main()
1 resposta

Oi, William! Como vai?

Agradeço por compartilhar.

Curti bastante como você aplicou herança e polimorfismo com a classe abstrata, deixando cada tipo de item com seu próprio desconto. Isso mostra um bom entendimento de organização orientada a objetos. Um ponto que chamou atenção está no método __str__ da sobremesa: o uso de super.__str__() pode causar problema,use super().__str__().

Uma dica interessante para o futuro é usar @property pra acessar atributos de forma mais controlada.


class Produto:
    def __init__(self, preco):
        self._preco = preco

    @property
    def preco(self):
        return self._preco

Esse código permite acessar preco como atributo, mas mantendo controle interno da variavel.

Conteúdos relacionados
Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!