4
respostas

Dicionários com itens mutáveis e imutáveis

Tenho uma aplicação e gostaria de verificar se é possível atendê-la com dicionários. A ideia é armazenar os seguintes dados de uma série de produtos:

  1. código: string, exemplo: 'SK1012'
  2. descricao: string, exemplo: 'Caneta esferográfica azul'
  3. preço: float, exemplo: 1.59
  4. quantidade em estoque: int, exemplo: 10000
  5. outras informações: strings contendo dados adicionais, exemplo: '16 cm', 'retrátil', 'ponta fina', em quantidade não especificada podendo ser zero ou mais informações.

Os produtos precisam ser recuperados pelo código. Após armazenados, os dados referentes ao código, descrição e outras informações não podem ser alterados, enquanto os dados referentes à quantidade em estoque e preço poderão ser modificados.

Estou experimentando combinar dicionários, listas e tuplas, mas não encontrei ainda uma solução.

4 respostas

Se você gostaria de armazenar esses dados, porque não simplesmente usar um banco de dados?

Fora isso, no Python, uma chave de um dicionário pode somente apontar para um objeto, mas esse objeto pode ser um outro dicionário ou lista. Talvez fazendo uso disso você possa criar um dicionário semelhante ao abaixo.

dict = {'SK1012': {'descricao': 'Caneta Azul', 'valor': 1.59, 'quantidade': 1000, 'outras_informacoes': ['retrátil', 'ponta fina'], ...}

Para acessar as informações, você teria que usar algo como "dict['SK1012']['descricao']".

Mas ainda assim, é sempre melhor usar um banco de dados. Eles foram feitos para isso, afinal. Conecte as informações a um banco de dados, crie uma classe para os produtos e extraia as informações direto para os atributos da classe.

Isso tornaria tudo mais organizado.

Eu li o seu comentário e decidi levá-lo como um desafio para hoje a fim de praticar o que aprendi na formação de POO na Alura.

Estava querendo fazer um banco de dados em uma classe. Contudo, aproveitei a ideia de Roberto Galhardi neste fórum e me baseei na criação de um arquivo .txt, como foi feito no jogo de Python nas aulas iniciais.

Acho que meu código tem ainda a ser melhorado e não atendi a todas as suas condições, Walmor Gomes, mas gostaria de exibir meu resultado:

def adiciona_txt(produto_novo):
    nome_arquivo = r"C:\Users\akhen\PycharmProjects\produto_forum\todos_produtos.txt"
    # Caminho do arquivo no meu computador.
    produto_str = str(produto_novo)

    # Leitura do arquivo
    with open(nome_arquivo, "r") as arquivo_leitura:
        adicionar = True
        for linha in arquivo_leitura:
            if produto_str in linha:
                adicionar = False
                print(f'Ítem {produto_novo["descricao"]} já existe. ')
        if adicionar:
            with open(nome_arquivo, "a") as arquivo:
                if adicionar:
                    print(f'Adicionando ítem {produto_novo["descricao"]}. ')
                    arquivo.write(produto_str + '\n')


class Adiciona:
    def __init__(self, produto_novo):
        self.produto_novo = produto_novo
        adiciona_txt(self.produto_novo)

    def __str__(self) -> str:
        return str(self.produto_novo)

    def __getitem__(self, item: int) -> str:
        return str(self.produto_novo[item])


class Produto:
    def __init__(self, codigo: str, descricao: str, preco: float, estoque: int, observacoes: str = ''):
        self.produto_adicionado = {
            'codigo': codigo,
            'descricao': descricao,
            'preco': preco,
            'estoque': estoque,
            'observacoes': observacoes
        }
        print("Lembrete que o preço é sempre em R$.")

    def __str__(self) -> str:
        return str(self.produto_adicionado)

    def __getitem__(self, item):
        erro = "Existem apenas 'codigo', 'descricao', 'preco', 'estoque' e 'observacoes'."
        if item in self.produto_adicionado:
            return self.produto_adicionado[item]
        else:
            raise ValueError(erro)


produto = Produto('SK1012',
                  'Caneta esferográfica azul',
                  1.59,
                  10000,
                  '16 cm, retrátil, ponta fina')
produto_2 = Produto('SK12646',
                    'Caneta esferográfica prateada',
                    1.29,
                    2000,
                    '133 mm, acionada por giro, ponta fina')

print(produto['codigo'])  # Para buscar o nome do código
Adiciona(produto)
Adiciona(produto_2)

nome_arquivo = r"C:\Users\akhen\PycharmProjects\produto_forum\todos_produtos.txt"
with open(nome_arquivo, "r") as arquivo_leitura:
    for linha in arquivo_leitura:
        print(linha)

"""
Exibirá no terminal:
Lembrete que o preço é sempre em R$.
Lembrete que o preço é sempre em R$.
Adicionando ítem Caneta esferográfica azul. 
Adicionando ítem Caneta esferográfica prateada. 


{'codigo': 'SK1012', 'descricao': 'Caneta esferográfica azul', 'preco': 1.59, 'estoque': 10000, 'observacoes': '16 cm, retrátil, ponta fina'}

{'codigo': 'SK12646', 'descricao': 'Caneta esferográfica prateada', 'preco': 1.29, 'estoque': 2000, 'observacoes': '133 mm, acionada por giro, ponta fina'}

"""

Para quem ler meu código, o que sugere de sugestão para deixá-lo menos redundante? Acho que a parte de leitura de arquivo ficaria melhor. Espero que tenha gostado, Walmor Gomes.

Na minha opinião, o código ficou bastante interessante.

No entanto, se me permite apontar, creio que notei um erro na sua criação de classes.

Como é dito pela própria teoria de POO, classes seriam representações de objetos reais, tais como carros, pessoas, funcionários e etc... Por outro lado, as ações realizadas por tais classes são representadas pelos métodos. Esses seriam correr, trabalhar, comer...

Logo, com isso em mente, a criação de uma classe "Adiciona" é, no mínimo, pouco intuitivo. Seria muito melhor transformar essa função em um método da classe produto. Você até mesmo chegou a criar a função "adiciona_txt", que poderia ser um método perfeitamente. No entanto, criar uma classe somente para inserir essa função é demais. Seu código ficaria bem mais legível se você adicionasse essa função como método a classe produto e deletasse a classe "Adiciona" completamente.

Classes não deveriam ser verbos. Elas devem ser substantivos. Verbos devem ser sempre métodos.

Passando agora ao seu código, conheço uma prática que pode te auxiliar na construção de loops for de uma forma mais intuitiva. Trata-se da estrutura for/else. Usando seu exemplo como caso, ao invés de escrever algo como:

# Leitura do arquivo
    with open(nome_arquivo, "r") as arquivo_leitura:
        adicionar = True
        for linha in arquivo_leitura:
            if produto_str in linha:
                adicionar = False
                print(f'Ítem {produto_novo["descricao"]} já existe. ')
        if adicionar:
            with open(nome_arquivo, "a") as arquivo:
                if adicionar:
                    print(f'Adicionando ítem {produto_novo["descricao"]}. ')
                    arquivo.write(produto_str + '\n')

Você poderia transformar para algo como:

# Leitura do arquivo
    with open(nome_arquivo, "r") as arquivo_leitura:
        for linha in arquivo_leitura:
            if produto_str in linha:
                print(f'Ítem {produto_novo["descricao"]} já existe. ')
        else:
            with open(nome_arquivo, "a") as arquivo:
                print(f'Adicionando ítem {produto_novo["descricao"]}. ')
                arquivo.write(produto_str + '\n')

A estrutura for/else funciona da seguinte maneira. Se o loop for não for acionado em nenhuma iteração, ou, no seu caso, caso nenhum produto seja detectado, a instrução else é executada. Seria algo semelhante a se não acontecer nada durante o laço for, execute o else.

Isso deixa o código mais legível e compacto.

Fora isso, muito boa a sua iniciativa!

Obrigado pelas sugestões, Roberto Galhardi. Acabei de realizar as mudanças no meu código para publicá-lo em meu GitHub. https://github.com/andradeSerafim/POO/blob/6b14dfff8f04a0def70e712fe0130ff8ee07057e/produtos_em_POO.py