Let's say I have 2 "empty" dicts:
keys_in = ["in1","in2"]
dict2 ={key: None for key in keys_in}
keys_out = ["out1","out2"]
dict3 ={key: None for key in keys_out}
And I want to "map" one of the values from a dict to the other:
dict3["out1"] = dict2["in1"]
So that if the value of dict2["in1"]
is set, I get the same value in dict3["out1"]
Is this possible? tried this and the value is not changed:
keys_in = ["in1","in2"]
dict2 ={key: None for key in keys_in}
keys_out = ["out1","out2"]
dict3 ={key: None for key in keys_out}
dict3["out1"] = dict2["in1"]
dict2["in1"] = 4
print(dict3["out1"]) #keeps being None
print(dict2["in1"]) # this of course is 4
I got this idea thinking on C pointers, I'm not sure if I'm in the right direction:s
CodePudding user response:
No, this is not how assignment works in Python. Please watch this or read this. tl;dr: names are reassigned independently.
Without any further context, you could create a mutable object and use it in the values of both dicts. I have never seen a use case for this and we're probably dealing with an XY-problem here, but an example might be educational.
class MutableValue:
def __init__(self, value):
self.value = value
def __repr__(self):
return repr(self.value)
Demo:
>>> dict1 = {'in1': MutableValue(4)}
>>> dict2 = {'out1': dict1['in1']}
>>> dict1
{'in1': 4}
>>> dict2
{'out1': 4}
>>> dict1['in1'].value = 5
>>> dict1
{'in1': 5}
>>> dict2
{'out1': 5}
Just for fun, we can take this further:
from collections import UserDict
class MutableValueDict(UserDict):
def __setitem__(self, key, item):
if key in self:
self[key].value = item
else:
super().__setitem__(key, MutableValue(item))
Demo:
>>> dict1 = MutableValueDict({'in1': 4})
>>> dict2 = MutableValueDict({'out1': dict1['in1']})
>>> dict1
{'in1': 4}
>>> dict2
{'out1': 4}
>>> dict1['in1'] = 5 # no need to access .value
>>> dict1
{'in1': 5}
>>> dict2
{'out1': 5}
CodePudding user response:
A tricky way to reach a similar result is to set a callable function to each value of the dependet disctionary, dict3
, which has access to the value stored in the original dictionary, dict2
. As drawbrack to access to a value in dict3
an empty call schould de done, i.e. dict3['out1']()
.
Natural assumption: both dictionary have the same amount of items (and the right order).
# default initialisation
keys_in = ["in1","in2"]
dict2 = dict.fromkeys(keys_in, None)
# create a dictionary with callable values
keys_out = ["out1","out2"]
dict3 = {k3: lambda: dict2[k2] for k2, k3 in zip(keys_in, keys_out)}
# check content
print(dict3['out1']())
# add content to first dict
dict2['in1'] = 'dict2 -> in1'
dict2['in2'] = 'dict2 -> in2'
# check the updates
print(dict3['out1']())
#'dict2 -> in1'
print(dict3['out1']())
#'dict2 -> in2'
Here an functional programming way to access to the values of the dict3
just to stress that all of its values are callables:
from operator import methodcaller
vs = list(map(methodcaller('__call__'), dict3.values()))
print(vs)