python, dicionários com chaves e atributos

Já postei um artigo semelhante a esse, relacionado a meta classes em python. Dessa vez, fui mais longe e acabei fazendo uma classe.

O lance é ter um dicionário parecido com o padrão do python, onde as chaves possam ser atributos e vice-versa. A limitação é que em hipótese alguma a chave pode ser algo diferente de uma string.

Pra resolver esse problema, coloquei uma opção strict=True no construtor da classe. Quando está em modo strict, ela gera um Exception se a chave não for uma string. Caso contrário, transforma o objeto em questão em uma string, com prefixo “_” e boas.


#!/usr/bin/env python
# coding: utf-8
# SuperDict 20081010 AF

class SuperDict(dict):
    def __init__(self, data=None, strict=True):
        self.__strict = strict
        if data:
            if type(data) is not dict:
                raise ValueError('argument is not a dictionary')

            for k, v in data.items(): self.__setitem__(k, v)

    def __setattr__(self, k, v):
        dict.__setattr__(self, k, v)
        if k != '_SuperDict__strict':
            dict.__setitem__(self, k, v)

    def __setitem__(self, k, v):
        if type(k) is not str:
            if self.__strict:
                raise ValueError('key "%s" is not string' % k)
            else:
                k = '_' + repr(k)

        self.__setattr__(k, v)

Em alguns casos, é muito mais prático usar um esse SuperDict que um dicionário comum. Ao criar uma nova chave no dicionário, tipo sd[‘chave’] = 10, ela estará automaticamene disponível como um atributo, tipo sd.chave.

Também, o caminho inverso funciona. O setattr pode ser implícito ou explícito, e o valor do novo atributo será uma nova chave no dicionário. Ao executar algo como sd.novachave = 10, ele irá executar o mesmo que sd[‘novachave’] = 10, mesmo que ela ainda não exista.

>>> from SuperDict import SuperDict
>>> sd = SuperDict({'nome':'Alexandre', 'sobrenome':'Fiori'})
>>> sd.idade = 28
>>> sd
{'idade': 28, 'sobrenome': 'Fiori', 'nome': 'Alexandre'}

Prático né?

UPDATE: o código abaixo é o que tenho usado atualmente… parece ser melhor e mais prático que o original do artigo.

class superdict(dict):
    def __setattr__(self, k, v):
        dict.__setitem__(self, k, v)

    def __delattr__(self, k):
        dict.__delitem__(self, k)

    def __getattr__(self, k):
        return k[:2] == '__' and dict.__getattr__(self, k) or dict.__getitem__(self, k)

    def __setitem__(self, k, v):
        if type(k) is not str: raise Exception('only string keys are allowed')
        elif not k[0].isalpha(): k = '_'+k
        dict.__setitem__(self, k, v)

Anúncios

One Comment on “python, dicionários com chaves e atributos”

  1. Bruno Tikami disse:

    Simples e prático como sempre, não ?

    Eu sinceramente não acho uma restrição tão grande o fato das keys só poderem ser strs.

    vlw pelo post.

    Tkm


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s