Various Dict Snippets
Reversable Dict
Dict accessible by Key or Value. Treated as though it were a Key Key dict. Unique Keys and Values.
import collections
class Reversable_Dict ( collections . MutableMapping ):
__slots__ = ( "_fwd" , "_rev" )
def __init__ ( s , * args , ** kwargs ):
s . _fwd = fwd = dict ( * args , ** kwargs )
s . _rev = dict (( v , k ) for k , v in fwd . items ())
def __delitem__ ( s , k ):
fwd , rev = s . _fwd , s . _rev
if k in fwd : return rev . pop ( fwd . pop ( k ))
if k in rev : return fwd . pop ( rev . pop ( k ))
raise KeyError , "%s not found." % k
def __getitem__ ( s , k ):
fwd , rev = s . _fwd , s . _rev
if k in fwd : return fwd [ k ]
if k in rev : return rev [ k ]
raise KeyError , "%s not found." % k
def __iter__ ( s ): return iter ( s . _fwd )
def __repr__ ( s ): return repr ( s . _fwd )
def __len__ ( s ): return len ( s . _fwd )
def __setitem__ ( s , k , v ):
try : s . __delitem__ ( k )
except KeyError : pass
try : s . __delitem__ ( v )
except KeyError : pass
s . _fwd [ k ] = v
s . _rev [ v ] = k
Tree Dict
Dict that inserts new Dicts when they’re missing.
class Tree_Dict ( dict ):
__slots__ = ()
def __missing__ ( s , k ):
v = s [ k ] = type ( s )()
return v
# Credit : http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python/19829714#19829714
Tracker Dict
Dict that keeps track of changes made to it. Not super performant, but is simple to use.
Checking dict_instance.diff returns a tuple of (New, Changed, Removed) or if nothing has changed, None.
try :
import cPickle as pickle
except ImportError :
import pickle
class Tracker_Dict ( dict ):
""" Dict that tracks changes. Changes = (New, Changed, Removed) """
def __init__ ( s , * args , ** kwargs ):
dict . __init__ ( s , * args , ** kwargs )
s . _diff = {}; s . diff
def diff ():
def fget ( s ):
diff1 = set ( dict . keys ( s )) # Current keys
diff2 = set ( s . _diff . keys ()) # Old keys
diff3 = dict (( a , pickle . dumps ( b , - 1 )) for a , b in dict . items ( s )) # Changes
new = diff1 - diff2 # New keys
rem = diff2 - diff1 # Removed keys
chg = set ( a for a , b in diff3 . items () if a in s . _diff and a not in new and a not in rem and b != s . _diff [ a ])
s . _diff = diff3
return ( new , chg , rem ) if new or chg or rem else None
def fset ( s , v ):
if v :
s . _diff = {}
else :
s . diff
return locals ()
diff = property ( ** diff ())
Zip Dict
Manage a zip file archive as a dict. Keys reflect relative path names to files and values the files themselves.
So add to the values using functions like pickle.dumps or json.dumps etc…
import shutil
import os.path
import zipfile
import collections
try :
import zlib
compress = zipfile . ZIP_DEFLATED
except ImportError :
compress = zipfile . ZIP_STORED
class Zip_Dict ( collections . MutableMapping ):
""" Manage Zip files as a Dict """
def __init__ ( s , path ):
s . _depth = 0
s . _mode = "r"
s . _path = path
s . _dirty = False
if os . path . isfile ( path ):
with s : s . _data = dict (( a , file ) for a in s . z . namelist ())
else :
s . _data = {}
s . _mode = "w"
with s : pass
def __enter__ ( s ):
if not s . _depth :
s . z = zipfile . ZipFile ( s . _path , s . _mode , compress )
s . _depth += 1
return s
def __exit__ ( s , * err ):
s . _depth -= 1
s . _mode = "r"
if not s . _depth :
if s . _dirty and not err [ 0 ]:
s . _dirty = False
dirty = set ( a for a , b in s . _data . items () if b is not file )
n = set ( s . z . namelist ())
if dirty - n and not dirty & n :
s . z . close ()
s . _mode = "a"
with s :
for k in dirty :
s . z . writestr ( k , s . _data [ k ])
else :
read = s . z
s . _mode = "w"
path , s . _path = s . _path , "%s.incomplete" % s . _path
try :
with s :
s . z . comment = read . comment
for k in s . _data :
if k in dirty :
s . z . writestr ( k , s . _data [ k ])
else :
s . z . writestr ( k , read . read ( k ))
read . close ()
shutil . move ( s . _path , path )
finally :
s . _path = path
s . _data = dict (( a , file ) for a in s . z . namelist ())
else :
s . z . close ()
def __iter__ ( s ): return iter ( s . _data )
def __repr__ ( s ): return repr ( s . _data )
def __len__ ( s ): return len ( s . _data )
def __getitem__ ( s , k ):
with s : return s . z . read ( k )
def __setitem__ ( s , k , v ):
with s :
s . _data [ k ] = v
s . _dirty = True
def __delitem__ ( s , k ):
with s :
del s . _data [ k ]
s . _dirty = True