ChainMap
Класс ChainMap
предназначен для быстрого связывания нескольких отображений, чтобы их можно было рассматривать как единое целое. Это намного быстрее, чем создание нового словаря и выполнение нескольких вызовов update()
.
Класс может использоваться для моделирования вложенных областей видимости и полезен при создании шаблонов. Класс группирует несколько словарей вместе для создания единого обновляемого представления. Если никаких словарей не передано - формируется отображение с единственным вложенным пустым словарем, так что новый ChainMap
всегда имеет хотя бы одно отображение.
Cопоставления хранятся в списке. Этот список доступен и может обновлен с помощью атрибута maps
. Запросы к представлению последовательно ищут во всех отображених, пока не будет найден верный ключ. Запись, обновление и удаление работают только с первым отображением.
ChainMap
реализует ссылки на включения. Это значит, если одно из отображений будет обновлено, эти изменения будут отражены в ChainMap
. Поддерживаются все обычные словарные методы. Кроме того, есть атрибут map
, метод для создания новых подконтекстов и свойство для доступа ко всем отображениям, кроме первого.
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
print('Keys = {}'.format(list(m.keys())))
>>> Keys = ['b', 'c', 'a']
print('Values = {}'.format(list(m.values())))
>>> Values = ['B', 'C', 'A']
print('Items:')
for k, v in m.items():
print('{} = {}'.format(k, v))
>>> Items:
>>> b = B
>>> c = C
>>> a = A
print('"d" in m: {}'.format(('d' in m)))
>>> "d" in m: False
Обновить значения можно как во вложениях, так и непосредственно. Во втором случае затрагивается только первое из отображений.
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
a['c'] = 'E'
print(m['c'])
>>> E
m['c'] = 'Z'
print(m['c'])
>>> Z
print(a)
>>> a = {'a': 'A', 'c': 'Z'}
Метод new_child()
позволяет создавать новый экземпляр ChainMap
с однои дополнительным отображением. Новое отображение можно заполнить сразу, передав в качестве аргумента метода.
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m1 = collections.ChainMap(a, b)
m2 = m1.new_child()
print(m2)
>>> ChainMap({}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m3 = m2.new_child({'a': 'E'})
print(m3)
>>> ChainMap({'a': 'E'}, {}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
Методе parents
возвращает новый экземпляр ChainMap
со всеми представлениями, за исключением первого.
Примеры реализации ChainMap
смотри тут
Пример вложенного контекста
c = ChainMap() # Create root context
d = c.new_child() # Create nested child context
e = c.new_child() # Child of c, independent from d
e.maps[0] # Current context dictionary -- like Python's locals()
e.maps[-1] # Root context -- like Python's globals()
e.parents # Enclosing context chain -- like Python's nonlocals
d['x'] = 1 # Set value in current context
d['x'] # Get first key in the chain of contexts
del d['x'] # Delete from current context
list(d) # All nested values
k in d # Check all nested values
len(d) # Number of nested values
d.items() # All nested items
dict(d) # Flatten into a regular dictionary