2011-08-22 18 views
35

¿Cuál es la diferencia entre UserDict, dict y ABC y cuál se recomienda? ¿Los documentos parecen despreciar UserDict?Subclase dict: ¿UserDict, dict o ABC?

También parece que el update() de UserDict usaría mi método setitem mientras que dict no? ¿Qué métodos son realmente esenciales para anular dada 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 una dict que hace dos cosas:

  • intern() todas las claves y valores
  • tienda de algunos de los valores en una base de datos SQLite

, pues, de UserDict, dict y ABC me permitiría hacer esto?

+0

Pero al menos algunos ABC también son útiles para simplificar implementaciones que no están basadas en tipos incorporados, como muestra este fragmento de la misma sección: 'Varios de los ABC también son útiles como mixins que lo hacen más fácil para desarrollar clases que soporten API de contenedor. Por ejemplo, para escribir una clase que soporte la API Set completa, solo es necesario proporcionar los tres métodos abstractos subyacentes: __conta __(), __iter __() y __len __(). El ABC suministra los métodos restantes, como __y __() y isdisjoint() ' – delnan

+1

Si desea probar si algo es un' dict', use 'isistance (x, dict)'. Si desea probarlo, es un tipo de mapeo, use 'isinstance (x, Mapping)'. Para eso está el ABC. Solo son útiles si cada tipo de mapeo usa 'Mapping.register()' o simplemente lo subclasifica directamente. Y sí, este ** es ** el propósito principal de un ABC. –

Respuesta

36

Si desea una colección personalizada que en realidad contenga los datos, la subclase dict. Esto es especialmente útil si desea ampliar la interfaz (por ejemplo, agregar métodos).

Ninguno de los métodos incorporados llamará a su personalizado __getitem__/__setitem__, sin embargo. Si necesita un control total sobre estos, cree una clase personalizada que implementa la clase base abstracta collections.MutableMapping en su lugar.

El ABC no proporciona un medio para almacenar los datos reales, solo una interfaz con implementaciones predeterminadas para algunos métodos. Estas implementaciones predeterminadas, sin embargo, llamarán a sus __getitem__ y __setitem__ personalizados. Tendrá que usar un dict interno para contener los datos, e implementar todos los métodos abstractos: __len__, __iter__, __getitem__, __setitem__ y __delitem__.

La clase UserDict desde el módulo de collections (en Python 2, el módulo se llama UserDict también) es una envoltura alrededor de un interior dict, la aplicación de la 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 usando un "real" interno dict como almacenamiento. Si desea una colección de almacenamiento tipo dict pero anula algunos métodos expuestos por dict, 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 ampliar 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.
+0

Gracias. De la publicación anterior aprendí sobre Mixins y ahora me di cuenta de que ABC proporciona implementaciones predeterminadas. Es un problema menor proporcionar una variable de datos, así que supongo que me acostumbraré al ABC – Gerenuk

+0

@agf: incluso 'DictMixin' requiere que implementes 5 métodos base. –

+0

@agf: El módulo' userdict 'se ha ido en Python 3.0, por eso dije que está obsoleto. http://www.python.org/dev/peps/pep-3108/ (Cita: "No es tan útil ya que los tipos pueden ser una superclase. Los bits útiles se movieron al módulo 'colecciones'") –

2

No use la clase UserDict - no la necesita. Como dicen los documentos, puede simplemente subclasificar dict directamente.

Sin embargo, todavía quieren que el módulo de UserDict, por DictMixin:

Nota:DictMixin, aunque no oficialmente obsoleta, se ha eliminado en Python 3, y se recomienda en la documentación que se utilizan collections.MutableMapping. Sin embargo, esto tiene un inconveniente: es necesario implementar más de la interfaz del diccionario: __delitem__, __getitem__, __iter__, __len__ y __setitem__. Con DictMixin, puede implementar los que desee 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 

Se convertirá automáticamente update utilizar su __setitem__ como desee.

+3

> Comenzando con Python versión 2.6, se recomienda usar collections.MutableMapping en lugar de DictMixin. – cwallenpoole

+3

@agf: Estás equivocado. El módulo 'UserDict' está en desuso y no debe usarse. ¿Cómo es más fácil usar 'UserDict.DictMixin' como una mezcla que usando' collections.MutableMapping' como una mezcla? Solo necesitará sobrescribir '__setitem __()' en ambos casos. –

+0

@agf: todo el módulo se ha ido en Python 3.x. –

Cuestiones relacionadas