tuple create comprehension python python-3.x dictionary data-structures collections

create - set() python



¿Cuál es el propósito de las colecciones.ChainMap? (4)

Me gustan los ejemplos de @ b4hand, y de hecho he utilizado en el pasado estructuras similares a las de ChainMap (pero no a la propia ChainMap) para los dos propósitos que menciona: anulaciones de configuración de múltiples capas y emulación de stack / scope variable.

Me gustaría señalar otras dos motivaciones / ventajas / diferencias de ChainMap , en comparación con el uso de un bucle de actualización de dict, por lo que solo se almacena la versión "final":

  1. Más información: dado que una estructura de ChainMap está "en capas", admite responder preguntas como: ¿Obtengo el valor "predeterminado" o uno anulado? ¿Cuál es el valor original ("predeterminado")? ¿A qué nivel se anuló el valor (ejemplo de configuración de borrowing @ b4hand: user-config o command-line-overrides)? Usando una dict sencilla, la información necesaria para responder estas preguntas ya está perdida.

  2. Corrección de velocidad: supongamos que tiene N capas y como máximo M claves en cada una, la construcción de un mapa de cadenas toma O(N) y cada búsqueda O(N) peor caso [*], mientras que la construcción de un dictado usando un ciclo de actualización toma O(NM) y cada búsqueda O(1) . Esto significa que si construyes a menudo y solo realizas algunas búsquedas cada vez, o si M es grande, el enfoque de construcción perezosa de ChainMap funciona a tu favor.

[*] El análisis en (2) asume que dict-access es O(1) , cuando de hecho es O(1) en promedio, y O(M) peor de los casos. Ver más detalles here .

En Python 3.3, se agregó una clase ChainMap al módulo de collections :

Se proporciona una clase ChainMap para vincular rápidamente una serie de asignaciones para que puedan tratarse como una sola unidad. A menudo es mucho más rápido que crear un nuevo diccionario y ejecutar múltiples llamadas de actualización ().

Ejemplo:

>>> from collections import ChainMap >>> x = {''a'': 1, ''b'': 2} >>> y = {''b'': 10, ''c'': 11} >>> z = ChainMap(y, x) >>> for k, v in z.items(): print(k, v) a 1 c 11 b 10

Fue motivado por este tema y hecho público por este (no se creó PEP ).

Por lo que yo entiendo, es una alternativa a tener un diccionario extra y mantenerlo con update() s.

Las preguntas son:

  • ¿Qué casos de uso cubre ChainMap ?
  • ¿Hay algún ejemplo del mundo real de ChainMap ?
  • ¿Se usa en bibliotecas de terceros que cambiaron a python3?

Pregunta de bonificación: ¿hay alguna forma de usarlo en Python2.x?

He escuchado sobre esto en Transforming Code into Beautiful, Idiomatic Python PyCon talk por Raymond Hettinger y me gustaría agregarlo a mi toolkit, pero me falta entender cuándo debería usarlo.


Para responder imperfectamente a tu:

Pregunta de bonificación: ¿hay alguna forma de usarlo en Python2.x?

from ConfigParser import _Chainmap as ChainMap

Sin embargo, tenga en cuenta que este no es un ChainMap real, hereda de DictMixin y solo define:

__init__(self, *maps) __getitem__(self, key) keys(self) # And from DictMixin: __iter__(self) has_key(self, key) __contains__(self, key) iteritems(self) iterkeys(self) itervalues(self) values(self) items(self) clear(self) setdefault(self, key, default=None) pop(self, key, *args) popitem(self) update(self, other=None, **kwargs) get(self, key, default=None) __repr__(self) __cmp__(self, other) __len__(self)

Su implementación tampoco parece particularmente eficiente.


Pude ver el uso de ChainMap para un objeto de configuración donde tiene múltiples ámbitos de configuración, como opciones de línea de comando, un archivo de configuración de usuario y un archivo de configuración del sistema. Como las búsquedas están ordenadas por orden en el argumento constructor, puede anular las configuraciones en ámbitos más bajos. No he usado ni visto personalmente el uso de ChainMap , pero eso no es sorprendente ya que es una adición bastante reciente a la biblioteca estándar.

También podría ser útil para emular marcos de pila en los que se insertan y se hacen saltar enlaces de variables si se intenta implementar un alcance léxico por su cuenta.

Los documentos de la biblioteca estándar para ChainMap ofrecen varios ejemplos y enlaces a implementaciones similares en bibliotecas de terceros. Específicamente, nombra la clase Contexto de Django y la clase MultiContext de Enthought.


Voy a analizar esto:

Chainmap parece una especie de abstracción. Es una buena solución para un tipo de problema muy especializado. Propongo este caso de uso.

Si usted tiene:

  1. mapeos múltiples (por ejemplo, dicts)
  2. cierta duplicación de claves en esas asignaciones (la misma clave puede aparecer en múltiples asignaciones, pero no en el caso de que todas las claves aparezcan en todas las asignaciones)
  3. una aplicación consumidora que desea acceder al valor de una clave en el mapeo de "prioridad más alta" donde hay un ordenamiento total sobre todas las asignaciones para una clave determinada (es decir, las asignaciones pueden tener la misma prioridad, pero solo si se sabe que no hay duplicaciones de clave dentro de esas asignaciones) (En la aplicación Python, los paquetes pueden vivir en el mismo directorio (misma prioridad) pero deben tener diferentes nombres, por lo que, por definición, los nombres de símbolos en ese directorio no pueden duplicarse).
  4. la aplicación consumidora no necesita cambiar el valor de una clave
  5. mientras que al mismo tiempo las asignaciones deben mantener su identidad independiente y pueden ser cambiadas asincrónicamente por una fuerza externa
  6. y las asignaciones son lo suficientemente grandes, lo suficientemente caras para acceder, o cambian con frecuencia entre los accesos a las aplicaciones, que el costo de calcular la proyección (3) cada vez que su aplicación lo necesita es un importante problema de rendimiento para su aplicación ...

Luego, podría considerar usar un mapa de cadena para crear una vista sobre la colección de asignaciones.

Pero esto es todo justificación después de los hechos. Los chicos de Python tuvieron un problema, idearon una buena solución en el contexto de su código y luego hicieron un trabajo extra para abstraer su solución para que pudiéramos usarla si así lo decidiéramos. Más poder para ellos. Pero si es apropiado para su problema depende de usted decidir.