Home > OS >  Mapping Values in multiple Python dicts
Mapping Values in multiple Python dicts

Time:06-29

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)
  • Related