actualización de dict de Python

¿Python tiene algún tipo de funcionalidad incorporada para notificar qué elementos del diccionario cambiaron en la actualización del dict? Por ejemplo, estoy buscando alguna funcionalidad como esta:

>>> a = {'a':'hamburger', 'b':'fries', 'c':'coke'} >>> b = {'b':'fries', 'c':'pepsi', 'd':'ice cream'} >>> a.diff(b) {'c':'pepsi', 'd':'ice cream'} >>> a.update(b) >>> a {'a':'hamburger', 'b':'fries', 'c':'pepsi', 'd':'ice cream'} 

Estoy buscando obtener un diccionario de los valores cambiados como se muestra en el resultado de a.diff (b)

No, pero puede crear una subclase de dictado para notificar el cambio.

 class ObservableDict( dict ): def __init__( self, *args, **kw ): self.observers= [] super( ObservableDict, self ).__init__( *args, **kw ) def observe( self, observer ): self.observers.append( observer ) def __setitem__( self, key, value ): for o in self.observers: o.notify( self, key, self[key], value ) super( ObservableDict, self ).__setitem__( key, value ) def update( self, anotherDict ): for k in anotherDict: self[k]= anotherDict[k] class Watcher( object ): def notify( self, observable, key, old, new ): print "Change to ", observable, "at", key w= Watcher() a= ObservableDict( {'a':'hamburger', 'b':'fries', 'c':'coke'} ) a.observe( w ) b = {'b':'fries', 'c':'pepsi'} a.update( b ) 

Tenga en cuenta que la superclase Watcher que se define aquí no verifica si hubo un cambio “real” o no; simplemente nota que hubo un cambio.

un año después

Me gusta la siguiente solución:

 >>> def dictdiff(d1, d2): return dict(set(d2.iteritems()) - set(d1.iteritems())) ... >>> a = {'a':'hamburger', 'b':'fries', 'c':'coke'} >>> b = {'b':'fries', 'c':'pepsi', 'd':'ice cream'} >>> dictdiff(a, b) {'c': 'pepsi', 'd': 'ice cream'} 

No, no lo hace. Pero no es difícil escribir una función de diferencia de diccionario:

 def diff(a, b): diff = {} for key in b.keys(): if (not a.has_key(key)) or (a.has_key(key) and a[key] != b[key]): diff[key] = b[key] return diff 

Una simple función de diferenciación es fácil de escribir. Dependiendo de la frecuencia con la que lo necesite, puede ser más rápido que el ObservableDict más elegante de S.Lott.

 def dict_diff(a, b): """Return differences from dictionaries a to b. Return a tuple of three dicts: (removed, added, changed). 'removed' has all keys and values removed from a. 'added' has all keys and values that were added to b. 'changed' has all keys and their values in b that are different from the corresponding key in a. """ removed = dict() added = dict() changed = dict() for key, value in a.iteritems(): if key not in b: removed[key] = value elif b[key] != value: changed[key] = b[key] for key, value in b.iteritems(): if key not in a: added[key] = value return removed, added, changed if __name__ == "__main__": print dict_diff({'foo': 1, 'bar': 2, 'yo': 4 }, {'foo': 0, 'foobar': 3, 'yo': 4 }) 
 def diff_update(dict_to_update, updater): changes=dict((k,updater[k]) for k in filter(lambda k:(k not in dict_to_update or updater[k] != dict_to_update[k]), updater.iterkeys())) dict_to_update.update(updater) return changes a = {'a':'hamburger', 'b':'fries', 'c':'coke'} b = {'b':'fries', 'c':'pepsi'} >>> print diff_update(a, b) {'c': 'pepsi'} >>> print a {'a': 'hamburger', 'c': 'pepsi', 'b': 'fries'} 

No está incorporado, pero puede iterar en las teclas del dictado y hacer comparaciones. Aunque podría ser lento.

Una mejor solución es probablemente construir una estructura de datos más compleja y usar un diccionario como la representación subyacente.