Quiero escribir una clase personalizada que se comporte como dict
, entonces, estoy heredando dict
.
Mi pregunta, sin embargo, es: ¿Necesito crear un dict
miembro privado en mi __init__()
método? No veo el sentido de esto, ya que ya tengo el dict
comportamiento si simplemente heredo de dict
.
¿Alguien puede señalar por qué la mayoría de los fragmentos de herencia se parecen al siguiente?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
En lugar de lo más simple ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
De hecho, creo que sospecho que la respuesta a la pregunta es que los usuarios no pueden acceder directamente a su diccionario (es decir, tienen que utilizar los métodos de acceso que ha proporcionado).
Sin embargo, ¿qué pasa con el operador de acceso a la matriz []
? ¿Cómo se implementaría eso? Hasta ahora, no he visto un ejemplo que muestre cómo anular el []
operador.
Entonces si un []
no se proporciona función de acceso en la clase personalizada, ¿los métodos base heredados operarán en un diccionario diferente?
Probé el siguiente fragmento para probar mi comprensión de la herencia de 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]
Tuve el siguiente error:
KeyError: <identificación de función incorporada>
¿Qué pasa con el código anterior?
¿Cómo corrijo la clase myDict
para poder escribir código como este?
md = myDict()
md['id'] = 123
[Editar]
He editado el ejemplo de código anterior para deshacerme del tonto error que cometí antes de salir corriendo de mi escritorio. Fue un error tipográfico (debería haberlo visto en el mensaje de error).
fuente
dict
, entonces debe usar el objeto en sí (usosuper
) en lugar de simplemente delegar a la instancia, lo__dict__
que esencialmente significa que está creando dos dictados para cada instancia._dict__
que contiene todos los atributos del objeto (métodos, campos, etc.). Tu no quiere perder el tiempo con esto a menos que usted quiere escribir código que se modifica a sí mismo ...Me gusta esto
Ahora puede usar las funciones integradas, como
dict.get()
asself.get()
.No es necesario envolver un archivo oculto
self._dict
. Tu clase ya es un dict.fuente
dict
sin llamar primero a su constructor.dict
realidad contiene 2 dict-instance: el primero es el contenedor heredado y el segundo es el dict que contiene los atributos de clase; puede evitarlo utilizando ranuras .__dict__
realidad, solo se crea cuando se accede por primera vez, por lo que siempre que los usuarios no intenten usarlo, está bien.__slots__
aunque estaría bien.En aras de la integridad, aquí está el enlace a la documentación mencionada por @ björn-pollex para la última versión de Python 2.x (2.7.7 en el momento de escribir este artículo):
Emulación de tipos de contenedores
(Lo siento por no usar la función de comentarios, pero stackoverflow no me permite hacerlo).
fuente
El problema con este fragmento de código:
... es que su método 'agregar' (... y cualquier método que desee que sea miembro de una clase) necesita tener un 'self' explícito declarado como su primer argumento, como:
Para implementar la sobrecarga del operador para acceder a elementos por clave, busque en los documentos los métodos mágicos
__getitem__
y__setitem__
.Tenga en cuenta que debido a que Python usa Duck Typing, es posible que en realidad no haya razón para derivar su clase dict personalizada de la clase dict del lenguaje, sin saber más sobre lo que está tratando de hacer (por ejemplo, si necesita pasar una instancia de esto class en algún código en algún lugar que se rompa a menos que
isinstance(MyDict(), dict) == True
), es mejor que simplemente implemente la API que hace que su clase sea lo suficientemente similar a un dictado y se detenga allí.fuente
Aquí hay una solución alternativa:
fuente
Realmente no veo la respuesta correcta a esto en ningún lado
Todo lo que realmente tienes que hacer es definir el tuyo
__init__
, eso es todo lo que hay.Otro ejemplo (un poco más complejo):
Este último ejemplo es útil cuando desea incrustar algún tipo de lógica.
De todos modos ... en resumen
class GiveYourClassAName(dict)
es suficiente para hacer que tu clase actúe como un dictado. Cualquier operación de dictado que realiceself
será como un dictado normal.fuente
Ésta es mi mejor solución. Usé esto muchas veces.
Puedes usar como:
fuente
¡Nunca heredes del dict incorporado de Python! por ejemplo, el
update
método no se usa__setitem__
, hacen mucho para la optimización. Utilice UserDict.fuente