Quero escrever uma classe personalizada que se comporte assim dict
- então, estou herdando de dict
.
Minha pergunta, porém, é: Preciso criar um dict
membro privado em meu __init__()
método? Não vejo sentido nisso, já que tenho o dict
comportamento de simplesmente herdar de dict
.
Alguém pode apontar por que a maioria dos snippets de herança se parece com o abaixo?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Em vez do mais simples ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
Na verdade, acho que suspeito que a resposta à pergunta seja para que os usuários não possam acessar diretamente o seu dicionário (ou seja, eles precisam usar os métodos de acesso que você forneceu).
No entanto, e quanto ao operador de acesso à matriz []
? Como alguém implementaria isso? Até agora, não vi um exemplo que mostra como substituir o []
operador.
Portanto, se uma []
função de acesso não for fornecida na classe personalizada, os métodos de base herdados estarão operando em um dicionário diferente?
Tentei o seguinte snippet para testar minha compreensão da herança do Python:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(self, id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
print md[id]
Recebi o seguinte erro:
KeyError: <id da função integrada>
O que há de errado com o código acima?
Como faço para corrigir a classe myDict
para poder escrever um código como este?
md = myDict()
md['id'] = 123
[Editar]
Eu editei o exemplo de código acima para me livrar do erro bobo que cometi antes de sair correndo de minha mesa. Foi um erro de digitação (eu deveria ter percebido na mensagem de erro).
fonte
dict
, deverá usar o próprio objeto (usingsuper
) em vez de simplesmente delegar à instância__dict__
- o que significa essencialmente que você está criando dois dicts para cada instância._dict__
que contém todos os atributos do objeto (métodos, campos, etc). Você não quer mexer com isso, a menos que queira escrever um código que está se modificando ...Como isso
Agora você pode usar as funções integradas, como
dict.get()
asself.get()
.Você não precisa embrulhar um oculto
self._dict
. Sua aula já é um dict.fonte
dict
sem chamar seu construtor primeiro.dict
contém, na verdade, 2 instâncias de dict: a 1ª é o contêiner herdado e a 2ª é o dicionário que contém os atributos de classe - você pode evitar isso usando slots .__dict__
verdade, o é criado apenas quando é acessado pela primeira vez, portanto, desde que os usuários não tentem usá-lo, tudo bem.__slots__
seria bom embora.Para fins de integridade, aqui está o link para a documentação mencionada por @ björn-pollex para o Python 2.x mais recente (2.7.7 no momento da escrita):
Emulando tipos de contêineres
(Desculpe por não usar a função de comentários, só não tenho permissão para fazer isso por stackoverflow.)
fonte
O problema com este pedaço de código:
... é que o seu método 'adicionar' (... e qualquer método que você deseja que seja membro de uma classe) precisa ter um 'self' explícito declarado como seu primeiro argumento, como:
Para implementar a sobrecarga do operador para acessar itens por chave, procure na documentação os métodos mágicos
__getitem__
e__setitem__
.Observe que, como o Python usa Duck Typing, pode não haver razão para derivar sua classe dict personalizada da classe dict da linguagem - sem saber mais sobre o que está tentando fazer (por exemplo, se você precisa passar uma instância deste classe em algum código em algum lugar que irá quebrar, a menos que
isinstance(MyDict(), dict) == True
), você pode ser melhor apenas implementar a API que torna sua classe suficientemente semelhante a dict e parar por aí.fonte
Aqui está uma solução alternativa:
fonte
Eu realmente não vejo a resposta certa para isso em lugar nenhum
Tudo o que você realmente precisa fazer é definir o seu próprio
__init__
- isso realmente é tudo o que existe.Outro exemplo (um pouco mais complexo):
Este último exemplo é útil quando você deseja incorporar algum tipo de lógica.
Enfim ... em suma,
class GiveYourClassAName(dict)
é o suficiente para fazer sua classe agir como um dit. Qualquer operação de comando que você fizerself
será como um comando normal.fonte
Esta é minha melhor solução. Eu usei isso muitas vezes.
Você pode usar como:
fonte
Não herde do dicionário interno do Python, nunca! por exemplo, o
update
método não seria usado__setitem__
, eles fazem muito para otimização. Use UserDict.fonte