Try this
# use the union of the keys and construct a list if a key exists in both dicts
# otherwise get the value of the key from the dict it exists in
{k:[dict_1[k], dict_2[k]] if all(k in d for d in [dict_1, dict_2]) else (dict_1.get(k) or dict_2.get(k)) for k in set(dict_1).union(dict_2)}
# {'x': [1, 'hello'], 'q': 19, 'y': [2, 'world'], 'z': [3, 123], 'p': 4}
This can be written (hopefully) a little more readably by using next
and walrus operator
:
{k: next(i for i in v if i is not None) if None in (v:=[dict_1.get(k), dict_2.get(k)]) else v for k in set(dict_1).union(dict_2)}
The same code as a normal loop:
dict_3 = {}
# loop over the union of the keys
for k in set(dict_1).union(dict_2):
# construct the list from the values
v = [dict_1.get(k), dict_2.get(k)]
# if a key doesn't exist in one of the dicts, it will dict.get() will give None
if None in v:
# in which case, get the non-None value
dict_3[k] = next(i for i in v if i is not None)
# otherwise, i.e. a key exists in both dicts,
else:
dict_3[k] = v