Reputation: 2022
I have different dictionaries where the keys are pandas timestamp and values are function taking all one input argument.
In [172]: from collections import OrderedDict
In [173]: import pandas as pd
In [174]: def f(x):
...: pass
...: def g(x):
...: pass
...: def h(x):
...: pass
...:
In [175]: dictionary = OrderedDict(zip(keys, [f, g, h]))
In [176]: def l(x):
...: pass
...:
In [177]: dictionary2 = OrderedDict(zip(pd.date_range('20190101', '20200101', freq='BA'), [l]))
Now I would like to update dictionary
with dictionary2
and if they are sharing keys the updated dictionary should hold a function which is the sum of the others. If I do a simple update it just overrides it:
In [178]: dictionary.update(zip(dictionary2.keys(), dictionary2.values()))
In [179]: dictionary
Out[179]:
OrderedDict([(Timestamp('2018-12-31 00:00:00', freq='BA-DEC'),
<function __main__.f>),
(Timestamp('2019-12-31 00:00:00', freq='BA-DEC'),
<function __main__.l>),
(Timestamp('2020-12-31 00:00:00', freq='BA-DEC'),
<function __main__.h>)])
However what I would like to have is that we get a new function (name doesnt matter) which is the sum of g
and l
in this case. There are two question:
Is there another way of defining a sum of function than:
In [180]: def H(f, g):
...: def _h(x):
...: return f(x) + g(x)
...: return _h
...:
In [181]:
How do I update then a dict in a pythonic way.
Upvotes: 0
Views: 542
Reputation: 114330
The simplest solution I can think of is to process the keys that overlap using a dict comprehension, then update dictionary
with dictionary2
followed by the overlaps.
To find the sums:
sums = {k: lambda x, f1=dictionary[k], f2=dictionary2[k]: f1(x) + f2(x) for k in dictionary2 if k in dictionary}
A lambda should be fine since you explicitly state that the name of the function is irrelevant. I cheat a little and extract the dictionary values up front using the default parameters to the lambda, whose values are bound immediately in each iteration of the comprehension. If I had done dictionary[k](x) + dictionary2[k](x)
in the lambda, the functions would only be bound when the lambda is called, by which point the value from dictionary
would have been lost.
Your way of doing the sum is arguably more Pythonic than what I propose here with a lambda with two additional parameters:
def s(f, g):
def h(x): return f(x) + g(x)
return h
sums = {k: s(dictionary[k], dictionary2[k]) for k in dictionary2 if k in dictionary}
To update:
dictionary.update(dictionary2)
dictionary.update(sums)
Upvotes: 1