Criação de dicionários com chaves pré-definidas
-
03-07-2019 - |
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?
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ê:.)