midict package API¶
midict.AttrDict¶
-
class
midict.
AttrDict
(*args, **kw)[source]¶ Bases:
dict
A dictionary that can get/set/delete a key using the attribute syntax if it is a valid Python identifier. (
d.key
<==>d['key']
)Note that it treats an attribute as a dictionary key only when it can not find a normal attribute with that name. Thus, it is the programmer’s responsibility to choose the correct syntax while writing the code.
Be aware that besides all the inherited attributes, AttrDict has an additional internal attribute “_AttrDict__attr2item”.
Examples:
d = AttrDict(__init__='value for key "__init__"') d.__init__ -> <bound method AttrDict.__init__> d["__init__"] -> 'value for key "__init__"'
-
__init__
(*args, **kw)[source]¶ Init the dict using the same arguments for
dict
.set any attributes here (or in subclass) - before __init__() so that these remain as normal attributes
-
__getattr__
(item)[source]¶ Maps values to attributes. Only called if there isn’t an attribute with this name
-
-
class
midict.
AttrOrdDict
(*args, **kw)[source]¶ Bases:
midict.AttrDict
,collections.OrderedDict
AttrDict + OrderedDict
midict.IndexDict¶
-
class
midict.
IndexDict
(*args, **kw)[source]¶ Bases:
dict
A dictionary that supports flexible indexing (get/set/delete) of multiple keys via an int, tuple, list or slice object.
The type of a valid key in IndexDict should not be int, tuple, or NoneType.
To index one or more items, use a proper
item
argument with the bracket syntax:d[item]
. The possible types and contents ofitem
as well as the corresponding values are summarized as follows:type content of the item
argumentcorresponding values int the index of a key in d.keys() the value of the key tuple/list multiple keys or indices of keys list of values slice “key_start : key_stop : step” list of values other types a normal key the value of the key The tuple/list syntax can mix keys with indices of keys.
The slice syntax means a range of keys (like the normal list slicing), and the
key_start
andkey_stop
parameter can be a key, the index of a key, or None (which can be omitted).When setting items, the slice and int syntax (including int in the tuple/list syntax) can only be used to change values of existing keys, rather than set values for new keys.
Examples:
d = IndexDict(a=1,b=2,c=3) d -> {'a': 1, 'c': 3, 'b': 2} d.keys() -> ['a', 'c', 'b'] d['a'] -> 1 d[0] -> 1 d['a','b'] <==> d[('a','b')] <==> d[['a','b']] -> [1, 2] d[:] -> [1,3,2] d['a':'b'] <==> d[0:2] <==> d['a':2] <==> d['a':-1] -> [1, 3] d[0::2] -> [1, 2] d[0] = 10 # d -> {'a': 10, 'c': 3, 'b': 2} d['a':-1] = [10, 30] # d -> {'a': 10, 'c': 30, 'b': 2} d[5] = 10 -> KeyError: 'Index out of range of keys: 5'
-
class
midict.
IdxOrdDict
(*args, **kw)[source]¶ Bases:
midict.IndexDict
,midict.AttrDict
,collections.OrderedDict
IndexDict + AttrDict + OrderedDict
midict.MIMapping¶
-
class
midict.
MIMapping
(*args, **kw)[source]¶ Bases:
midict.AttrOrdDict
Base class for all provided multi-index dictionary (MIDict) types.
Mutable and immutable MIDict types extend this class, which implements all the shared logic. Users will typically only interact with subclasses of this class.
-
__init__
(*args, **kw)[source]¶ Init dictionary with items and index names:
(items, names, **kw) (dict, names, **kw) (MIDict, names, **kw)
names
andkw
are optional.names
must all be str or unicode type. Whennames
not present, index names default to: ‘index_0’, ‘index_1’, etc. When keyword arguments present, only two indices allowed (like a normal dict)Examples:
index_names = ['uid', 'name', 'ip'] rows_of_data = [[1, 'jack', '192.1'], [2, 'tony', '192.2']] user = MIDict(rows_of_data, index_names) user = MIDict(rows_of_data) <==> user = MIDict(rows_of_data, ['index_0', 'index_1', 'index_2'])
Construct from normal dict:
normal_dict = {'jack':1, 'tony':2} user = MIDict(normal_dict.items(), ['name', 'uid']) # user -> MIDict([['tony', 2], ['jack', 1]], ['name', 'uid'])
-
__eq__
(other)[source]¶ Test for equality with
other
.if
other
is a regular mapping/dict, compare only order-insensitive keys/values. ifother
is also a OrderedDict, also compare the order of keys. ifother
is also a MIDict, also compare the index names.
-
__lt__
(other)[source]¶ Check if
self < other
If
other
is not a Mapping type, return NotImplemented.- If
other
is a Mapping type, compare in the following order: - convert
self
to an OrderedDict or a dict (depends on the type ofother
) and compare it withother
- index names (only if
other
is a MIMapping)
- convert
- If
-
clear
(clear_indices=False)[source]¶ Remove all items. index names are removed if
clear_indices==True
.
-
classmethod
fromkeys
(keys, value=None, names=None)[source]¶ Create a new dictionary with keys from
keys
and values set tovalue
.fromkeys() is a class method that returns a new dictionary.
value
defaults to None.Length of
keys
must not exceed one because no duplicate values are allowed.Optional
names
can be provided for index names (of length 2).
-
get
(key, default=None)[source]¶ Return the value for
key
ifkey
is in the dictionary, elsedefault
. Ifdefault
is not given, it defaults to None, so that this method never raises aKeyError
.Support “multi-indexing” keys
-
__contains__
(key)[source]¶ Test for the presence of
key
in the dictionary.Support “multi-indexing” keys
-
__reversed__
(index=None)[source]¶ Iterate in reversed order through keys in the
index
(defaults to the first index)
-
keys
(index=None)[source]¶ a set-like object providing a view on the keys in
index
(defaults to the first index)
-
itervalues
(index=None)[source]¶ Iterate through values in the
index
(defaults to all indices except the first index).When
index is None
, yielded values depend on the length of indices (N
):- if N <= 1: return
- if N == 2: yield values in the 2nd index
- if N > 2: yield values in all indices except the first index
(each value is a list of
N-1
elements)
-
values
(index=None)[source]¶ a set-like object providing a view on the values in
index
(defaults to all indices except the first index)
-
items
(index=None)[source]¶ a set-like object providing a view on the items in
index
(defaults to all indices)
-
midict.MIDict¶
-
class
midict.
MIDict
(*args, **kw)[source]¶ Bases:
midict.MIMapping
MIDict is an ordered “dictionary” with multiple indices where any index can serve as “keys” or “values”, capable of assessing multiple values via its powerful indexing syntax, and suitable as a bidirectional/inverse dict (a drop-in replacement for dict/OrderedDict in Python 2 & 3).
Features:
- Multiple indices
- Multi-value indexing syntax
- Convenient indexing shortcuts
- Bidirectional/inverse dict
- Compatible with normal dict in Python 2 & 3
- Accessing keys via attributes
- Extended methods for multi-indices
- Additional APIs to handle indices
- Duplicate keys/values handling
-
__setitem__
(args, value)[source]¶ set values via multi-indexing
If
d.indices
is empty (i.e., no index names and no items are set), index names can be created when setting a new item with specified names (index1
andindex2
can not be int or slice):d = MIDict() d['uid':1, 'name'] = 'jack' # d -> MIDict([[1, 'jack']], ['uid', 'name']) d = MIDict() d[1] = 'jack' # using default index names <==> d[:'jack'] = 1 # d -> MIDict([(1, 'jack')], ['index_1', 'index_2'])
If
d.indices
is not empty, when setting a new item, all indices of the item must be specified viaindex1
andindex2
(implicitly or explicitly):d = MIDict([['jack', 1, '192.1']], ['name', 'uid', 'ip']) d['tony'] = [2, '192.2'] <==> d['name':'tony',['uid', 'ip']] = [2, '192.2'] # the following will not work: d['alice', ['uid']] = [3] # raise ValueError
More examles:
d = MIDict(jack=1, tony=2) d['jack'] = 10 # replace value of key 'jack' d['tom'] = 3 # add new key/value d['jack'] = 2 # raise ValueExistsError d['alice'] = 2 # raise ValueExistsError d[:2] = 'jack' # raise ValueExistsError d['jack', :] = ['tony', 22] # raise ValueExistsError d['jack', :] = ['jack2', 11] # replace item of key 'jack'
-
clear
(clear_indices=False)[source]¶ Remove all items. index names are removed if
clear_indices==True
.
-
update
(*args, **kw)[source]¶ Update the dictionary with items and names:
(items, names, **kw) (dict, names, **kw) (MIDict, names, **kw)
Optional positional argument
names
is only allowed whenself.indices
is empty (no indices are set yet).
midict.FrozenMIDict¶
-
class
midict.
FrozenMIDict
(*args, **kw)[source]¶ Bases:
midict.MIMapping
,collections.abc.Hashable
An immutable, hashable multi-index dictionary (similar to
MIDict
).
Exceptions¶
-
exception
midict.
ValueExistsError
[source]¶ Bases:
KeyError
,midict.MIMappingError
Value already exists in an index and can not be used as a key.
Usage:
ValueExistsException(value, index_order, index_name)
Dict views¶
-
class
midict.
MIKeysView
(mapping, index=None)[source]¶ Bases:
collections.abc.KeysView
a set-like object providing a view on the keys in
index
(defaults to the first index)
-
class
midict.
MIValuesView
(mapping, index=None)[source]¶ Bases:
collections.abc.ValuesView
a set-like object providing a view on the values in
index
(defaults to all indices except the first index)
Auxiliary functions¶
-
midict.
cvt_iter
(a)[source]¶ Convert an iterator/generator to a tuple so that it can be iterated again.
E.g., convert zip in PY3.
-
midict.
convert_dict
(d, cls=<class 'midict.AttrDict'>)[source]¶ recursively convert a normal Mapping d and it’s values to a specified type (defaults to AttrDict)
-
midict.
convert_key_to_index
(keys, key)[source]¶ convert
key
of various types to int or list of intreturn index, single
-
midict.
convert_index_to_keys
(d, item)[source]¶ Convert
item
in various types (int, tuple/list, slice, or a normal key) to a single key or a list of keys.
-
midict.
get_unique_name
(name='', collection=())[source]¶ Generate a unique name (str type) by appending a sequence number to the original name so that it is not contained in the collection.
collection
has a __contains__ method (tuple, list, dict, etc.)
-
midict.
get_value_len
(value)[source]¶ Get length of
value
. Ifvalue
(eg, iterator) has no len(), convert it to list first.return both length and converted value.
-
midict.
MI_parse_args
(self, args, ingore_index2=False, allow_new=False)[source]¶ Parse the arguments for indexing in MIDict.
Full syntax:
d[index1:key, index2]
.index2
can be flexible indexing (int, list, slice etc.) as inIndexDict
.Short syntax:
- d[key] <==> d[key,] <==> d[first_index:key, all_indice_except_first]
- d[:key] <==> d[:key,] <==> d[None:key] <==> d[last_index:key, all_indice_except_last]
- d[key, index2] <==> d[first_index:key, index2] # this is valid # only when index2 is a list or slice object
- d[index1:key, index2_1, index2_2, ...] <==> d[index1:key, (index2_1, index2_2, ...)]
-
midict.
od_replace_key
(od, key, new_key, *args, **kw)[source]¶ Replace key(s) in OrderedDict
od
by new key(s) in-place (i.e., preserving the order(s) of the key(s))Optional new value(s) for new key(s) can be provided as a positional argument (otherwise the old value(s) will be used):
od_replace_key(od, key, new_key, new_value)To replace multiple keys, pass argument
key
as a list instance, or explicitly pass a keyword argumentmulti=True
:od_replace_key(od, keys, new_keys, [new_values,] multi=True)