I am a bit wiser or – how to combine dictionaries and see what changed
I currently had the problem of handling updates with partial settings of RGB lights through MQTT and HomeAssistant. As The setting has to be complete at all times in the running system, so my first solution were multiple if else clauses and changed flags. It works, but it is ugly and over-complicated. I didn’t use dictionaries for the settings at first, but a Setting class with the respective fields, a default configuration and an update method doing all the work. As I looked for something easier I found out about the bitwise or operator “|” which is implemented in dictionaries. Short story shorter:
# two dictionaries
a = {'state': 'off', 'brightness': 128}
b = {'state': 'on', 'color': [170, 60, 30]}
# combine them - second overwrites first, but keeps missing key/value pairs
print(a | b)
# output will be - value of state was changed, new key/value for color was added and brightness was kept:
# {'state': 'on', 'brightness': 128, 'color': [170, 60, 30]}
This simplified the task I had very much and made the custom class for this much smaller.
Another important thing I needed to know was which values of previously existing keys were changed and which key/value pairs were added. This can be done in a pretty handy list comprehension:
# two dictionaries and combined
a = {'state': 'off', 'brightness': 128}
b = {'state': 'on', 'color': [170, 60, 30]}
c = a | b
# list comprehensions for changed values and new keys
changed = [k for k in a.keys() if k in b.keys() and b[k] != a[k]]
new = [k for k in b.keys() if k not in a.keys()]
changed_or_new = [k for k in b.keys() if k not in a.keys() or b[k] != a[k]] # order of if statements matter
On a sidenote: not equal comparision (!=) needs __ne__(), equal (==) needs __eq__() function implemented.
With the information what changed in the dictionary, you can react differently checking if the changed/new list contain certain elements like:
# using the variables from the box above
if 'color' in changed and c['state'] == 'on':
change_color(c[color])
Just to mention it – as the names of the keys probably won’t change – they should be defines as constants. That way you can be lazy and use autocompletion in your IDE, reduce typos and the poor guy who has to refactor your code in the future (probably yourself) will thank you.
Have a nice ‘pysonic’ day! By FLUX1.schnell. 😀 As you have probably noticed – I love AI-generated images with hilarious errors hallucinations innovations.