python - herency - Dict de subclase: ¿UserDict, dict o ABC?
python superclasses (3)
Basado en el libro Secrets Recipes of the Python Ninja
Lo único especial que el UserDict tiene más allá de las operaciones normales del diccionario es un único atributo:
datos: un diccionario real para contener los contenidos de la clase UserDict
Para acceder a los elementos en el diccionario, debe iterar sobre ellos o llamar a elementos (). Si bien la instancia de UserDict admite los mismos métodos, la vista devuelta por los elementos () es notablemente diferente:
>>> from collections import UserDict >>> a = UserDict(a=1) >>> d = dict(d=3) # regular dictionary for comparison >>> for k in d: ... print(k, d[k]) ... d 3 >>> d.items() dict_items([(''d'', 3)]) >>> for k in a: ... print(k, a[k]) ... a 1 >>> a.items() ItemsView({''a'': 1})
Observe que el objeto de diccionario devuelve una tupla de clave / valores. El UserDict devuelve un objeto de diccionario real. Dependiendo de lo que esté haciendo, esta diferencia puede ser importante, como lo es la capacidad de usar el atributo de datos para acceder al diccionario.
¿Cuál es la diferencia entre UserDict
, dict
y ABC
y cuál se recomienda? ¿Los documentos parecen despreciar UserDict
?
También parece que la update()
de UserDict update()
usaría mi método setitem
mientras que dict
no? ¿Qué métodos son realmente esenciales para anular dado que quiero la función personalizada setitem
y getitem
?
Con ABC
s, tendría que implementar absolutamente todos los métodos, ya que no proporciona una implementación predeterminada.
Quiero hacer un dict
que haga dos cosas:
-
intern()
todas las claves y valores - almacenar algunos de los valores en una base de datos SQLite
Entonces, ¿qué tipo de UserDict
, dict
y ABC
me permitirán hacer esto?
No use la clase UserDict
, no la necesita. Como dicen los documentos, puedes simplemente subclasificar dict
directamente.
Sin embargo, aún desea el módulo DictMixin
para DictMixin
:
Nota: DictMixin
, aunque no se ha desaprobado oficialmente, se ha eliminado en Python 3, y se recomienda en los documentos que use collections.MutableMapping
. Sin embargo, esto tiene un inconveniente: debe implementar más de la interfaz del diccionario: __delitem__
, __getitem__
, __iter__
, __len__
, y __setitem__
. Con DictMixin
, puede implementar los que desea cambiar, y el resto usar una implementación predeterminada.
from UserDict import DictMixin
class MyDict(DictMixin, dict):
def __setitem__(self, key, value):
print key, value # just an example
# use intern(key) or whatever here
dict.__setitem__(self, key, value) # or
# super(MyDict, self).__setitem__(key, value)
m = MyDict()
m[''a''] = ''b''
# a b
m.update({''a'': ''c''})
# a c
Automáticamente hará que la update
use tu __setitem__
como quieras.
Si desea una colección personalizada que en realidad contenga los datos, subclase dict . Esto es especialmente útil si desea extender la interfaz (por ejemplo, agregar métodos).
Ninguno de los métodos incorporados llamará a su __getitem__
/ __setitem__
, sin embargo. Si necesita un control total sobre estos, cree una clase personalizada que implemente la clase base abstracta collections.MutableMapping
lugar.
El ABC no proporciona un medio para almacenar los datos reales, solo una interfaz con implementaciones predeterminadas para algunos métodos. Sin embargo, estas implementaciones predeterminadas llamarán a su __getitem__
y __setitem__
. Deberá usar un dict
interno para contener los datos e implementar todos los métodos abstractos: __len__
, __iter__
, __getitem__
, __setitem__
y __delitem__
.
La clase UserDict
del módulo de collections
(en Python 2, el módulo también se llama UserDict
) es un contenedor alrededor de un dict
interno, implementando el MutableMapping
ABC. Si desea personalizar el comportamiento de un dict
, esta implementación podría ser un punto de partida.
En resumen:
- MutableMapping define la interfaz. Subclase esto para crear algo que actúe como un
dict
. Depende totalmente de ti si y cómo almacenas los datos. - UserDict es una implementación de
MutableMapping
usa undict
interno "real" como almacenamiento. Si desea una colección de almacenamiento tipo dict pero anula algunos métodos expuestos pordict
, este podría ser un buen punto de partida para usted. Pero asegúrese de leer el código para saber cómo se implementan los métodos básicos, para que sea coherente al anular un método. - dict es "lo real". Subclase esto si desea extender la interfaz. Anular los métodos para hacer cosas personalizadas puede ser peligroso, ya que generalmente hay varias formas de acceder a los datos, y podrías terminar con una API inconsistente.