# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import collections

# ## Accessing Values
# The `ChainMap` manages a sequence of dictionaries, and searches through them in the order they are given, to find values associated with keys.

# +
a= {'a':'A','c':'C'}
b= {'b':'B','c':'D'}

m=collections.ChainMap(a,b)

print('Indivisual Values')
print('a={}'.format(m['a']))
print('b={}'.format(m['b']))
print('c={}'.format(m['c']))
print()

print('Keys={}'.format(list(m.keys())))
print('Value={}'.format(list(m.values())))

print()

print("Print Items")

for k,v in m.items():
    print('{}={}'.format(k,v))
    
print('"d" in m:{}'.format(('d' in m)))
# -

# **Note**
# The child mapping are searched in the order they are passed to the constructor, so the value reported for the key 'c' comes from the "a" dictionary.

# ## Reordering
#
# the ChainMap stores the list of mappings over which it searchs in a list in its maps attribute. This list is mutable. so it is possible to add new mappings directly or change the order of the elements to control lookup and update behavior

# +
import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)

print(m.maps)
print('c = {}\n'.format(m['c']))

# reverse the list
m.maps = list(reversed(m.maps))

print(m.maps)
print('c = {}'.format(m['c']))
# -

# ## Updating Values
#
# A ChainMap does not cache the values in the child mappings, thus, if their contents are modified, the results are reflected when ChainMap is accessed.

# +
import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m = collections.ChainMap(a, b)
print('Before: {}'.format(m['c']))
a['c'] = 'E'
print('After : {}'.format(m['c']))

# -

# ChainMap Provides a convenience method for creating a new instance with one extra mapping at the front of maps list to make it easy to avoid modifying the existing underlying data structures.

# +
import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}

m1 = collections.ChainMap(a, b)
m2 = m1.new_child()

print('m1 before:', m1)
print('m2 before:', m2)

m2['c'] = 'E'

print('m1 after:', m1)
print('m2 after:', m2)
# -

# for situation where the new context is known or buit in advance, it is also possible to pass a mapping to `new_child()'

# +
import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
c = {'c': 'E'}

m1 = collections.ChainMap(a, b)
m2 = m1.new_child(c)

print('m1["c"] = {}'.format(m1['c']))
print('m2["c"] = {}'.format(m2['c']))
# -

# we can also skip the first map in the search.
# `parents` Property returning a new `ChainMap` containing all of the maps in the current instance except the first one.

# +
import collections

a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
c = {'e': 'E', 'f': 'F'}


m1 = collections.ChainMap(a, b,c)
m1.parents
# -



StarcoderdataJupyterScriptsDedupFiltered