Как объединить два словаря в один таким образом, чтобы связывались ссылки
Допустим есть следующие словари:
dict1 = dict()
dict2 = dict()
dict1["поле"] = 1
dict2["кукуруза"] = 2
dictunion = dict()
Как в dictunion записать dict1 и dict2, т.е. привести к виду { "поле": 1 "кукуруза": 2 } , чтобы после изменения значений dict1 и dict2, допустим "поле": 10, а "кукуруза": 20 при выводе dictunion получилось следующее: { "поле": 10 "кукуруза": 20 }
Ответы (4 шт):
>>> x = {"key1": "value1 from x", "key2": "value2 from x"}
>>> y = {"key2": "value2 from y", "key3": "value3 from y"}
# объединение словаря `x` с `y`
>>> {**x, **y}
# {'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
# объединение словаря `y` с `x`
>>> {**y, **x}
# {'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}
# Новое в Python 3.9
>>> x | y
# {'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
>>> y | x
# {'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}
Если нужно использовать именно словарь, то никак. Python не позволит это сделать. В новый словарь всегда будут помещаться новые ссылки. Для лучшего понимания механизма рекомендую почитать про изменяемые и неизменяемые объекты.
Если же использование именно словарей не принципиально, то можно реализовать собственный класс с использованием __getitem__ и __setitem__, чтобы обращаться к полям с помощью ключей.
Например так:
class MyDict(object):
def __init__(self, inner_dict: dict):
self.inner_dict = inner_dict
def __getitem__(self, item):
return self.inner_dict[item]
def __setitem__(self, key, value):
self.inner_dict[key] = value
class MyDictUnion(object):
def __init__(self, my_dict_1: MyDict, my_dict_2: MyDict):
self.my_dict_1 = my_dict_1
self.my_dict_2 = my_dict_2
def __getitem__(self, item):
if item in self.my_dict_1.inner_dict:
return self.my_dict_1[item]
elif item in self.my_dict_2.inner_dict:
return self.my_dict_2[item]
def __setitem__(self, key, value):
if key in self.my_dict_1.inner_dict:
self.my_dict_1[key] = value
elif key in self.my_dict_2.inner_dict:
self.my_dict_2[key] = value
dict1 = MyDict({"поле": 1})
dict2 = MyDict({"кукуруза": 2})
dictunion = MyDictUnion(dict1, dict2)
dict1["поле"] = 10
print(dictunion["поле"])
Небольшое дополнение:
Класс MyDict, который я почему-то посчитал обязательным, на самом деле совершенно не нужен. Соответственно от него можно избавиться. А если в DictUnion дополнительно реализовать метод keys, то, в случае необходимости, объект можно будет преобразовать в словарь с помощью dict(dictunion). Но стоит учитывать, что это будет новый словарь, значения которого никак не зависят от dict1, dict2 и dictunion.
Моя реализация:
class DictUnion(object):
def __init__(self, dict_1: dict, dict_2: dict):
self.dict_1 = dict_1
self.dict_2 = dict_2
def __getitem__(self, item):
if item in self.dict_1:
return self.dict_1[item]
else:
return self.dict_2[item]
def __setitem__(self, key, value):
if key in self.dict_1:
self.dict_1[key] = value
else:
self.dict_2[key] = value
def keys(self):
return self.dict_1.keys() | self.dict_2.keys()
Простейший изменяемый объект – список из одного элемента. Да, изменится синтаксис, но вы получите полноценное разделяемое значение:
dict1 = dict()
dict2 = dict()
dict1["поле"] = [1] # вместо значений храним списки
dict2["кукуруза"] = [2] # из одного элемента
dictunion = dict1 | dict2
print(dictunion)
dict1["поле"][0] = 10 # ко всем обращениям
dict2["кукуруза"][0] = 20 # приписываем `[0]`
print(dictunion)
$ python refs.py {'поле': [1], 'кукуруза': [2]} {'поле': [10], 'кукуруза': [20]}