Pergunta

Em Python, há uma maneira de criar uma classe que é tratado como um dicionário, mas tenho as chaves pré-definido quando uma nova instância é criada?

Foi útil?

Solução

Você pode facilmente estender qualquer construído em tipo. Isto é como você faria com um dicionário:

>>> class MyClass(dict):
...     def __init__(self, *args, **kwargs):
...             self['mykey'] = 'myvalue'
...             self['mykey2'] = 'myvalue2'
...
>>> x = MyClass()
>>> x['mykey']
'myvalue'
>>> x
{'mykey2': 'myvalue2', 'mykey': 'myvalue'}

Eu não era capaz de encontrar a documentação Python que fala sobre isso, mas o livro muito popular Dive Into Python (disponível gratuitamente on-line) tem alguns exemplos em fazer isso.

Outras dicas

Você também pode ter a subclasse dict restringir as chaves para uma lista predefinida, substituindo __setitem__()

>>> class LimitedDict(dict):
    _keys = "a b c".split()
    def __init__(self, valtype=int):
        for key in LimitedDict._keys:
            self[key] = valtype()
    def __setitem__(self, key, val):
        if key not in LimitedDict._keys:
            raise KeyError
        dict.__setitem__(self, key, val)


>>> limited = LimitedDict()
>>> limited['a']
0
>>> limited['a'] = 3
>>> limited['a']
3
>>> limited['z'] = 0

Traceback (most recent call last):
  File "<pyshell#61>", line 1, in <module>
    limited['z'] = 0
  File "<pyshell#56>", line 8, in __setitem__
    raise KeyError
KeyError
>>> len(limited)
3

Sim, em Python dict é uma classe, para que possa subclasse-lo:

    class SubDict(dict):
        def __init__(self):
            dict.__init__(self)
            self.update({
                'foo': 'bar',
                'baz': 'spam',})

Aqui você substituir o método __init__() do dict (um método que é chamado quando uma instância da classe é criada). Dentro __init__ você método __init__() primeira chamada supercalss de, que é uma prática comum quando você whant para expandir a funcionalidade da classe base. Em seguida, você atualizar a nova instância do SubDictionary com seus dados inicial.

    subDict = SubDict()
    print subDict    # prints {'foo': 'bar', 'baz': 'spam'}

Eu não tenho certeza que isso é o que você está procurando, mas quando eu li o seu post eu imediatamente pensei que você estava procurando para gerar dinamicamente chaves para exercícios de contagem.

perl Ao contrário, o que vai fazer isso para você por padrão,


grep{$_{$_}++} qw/ a a b c c c /;
print map{$_."\t".$_{$_}."\n"} sort {$_{$b}$_{$a}} keys %_;

c   3
a   2
b   1

Python não vai lhe dar isso de graça:


l = ["a","a","b","c","c","c"]
d = {}
for item in l:
    d[item] += 1

Traceback (most recent call last):
  File "./y.py", line 6, in 
    d[item] += 1
KeyError: 'a'

No entanto, defaultdict vai fazer isso para você,


from collections import defaultdict
from operator import itemgetter

l = ["a","a","b","c","c","c"]
d = defaultdict(int)
for item in l:
    d[item] += 1

dl = sorted(d.items(),key=itemgetter(1), reverse=True)
for item in dl:
    print item

('c', 3)
('a', 2)
('b', 1)

Basta criar uma subclasse de dict e adicionar as chaves na init método.

class MyClass(dict)

def __init__(self):
    """Creates a new dict with default values""""

    self['key1'] = 'value1'

Lembre-se, porém, que em python qualquer classe que 'funciona como um dicionário' é geralmente tratada como um, para que você não precisa se preocupar muito com isso sendo uma subclasse, você poderia, em vez implementar os métodos de dicionários, embora o acima abordagem é provavelmente mais útil para você:.)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top