I'm using the following function to create a clone of a dictionary (which can be of arbitrary depth and structure) with decimals converted to floats. This will be used to deal with JSON returned from DynamoDB, but for fun I decided to make it as general-purpose as possible:
def all_decs_to_float(my_input):
"""Take an input and return a duplicate with all decs converted to floats."""
if isinstance(my_input, decimal.Decimal):
return float(my_input)
elif isinstance(my_input, dict):
return {k: all_decs_to_float(v) for k, v in my_input.items()}
elif isinstance(my_input, list):
return [all_decs_to_float(v) for v in my_input]
elif isinstance(my_input, set):
return {all_decs_to_float(v) for v in my_input}
elif isinstance(my_input, tuple):
# Tuple function is used here to avoid returning a generator item.
return tuple(all_decs_to_float(v) for v in my_input)
else:
return my_input
input/output:
>>> my_test_dict
{'item1': 'test', 'item2': {'item3': 2.0, 'item4': {'item5': Decimal('3')}, 'l': [1, 2, '3', Decimal('4'), 5], 's': {1, 2, Decimal('4'), 5, '3'}, 't': (1, 2, '3', Decimal('4'), 5)}}
>>> all_decs_to_float(my_test_dict)
{'item1': 'test', 'item2': {'item3': 2.0, 'item4': {'item5': 3.0}, 'l': [1, 2, '3', 4.0, 5], 's': {1, 2, 4.0, 5, '3'}, 't': (1, 2, '3', 4.0, 5)}}
I want to avoid modifying the original object (I think it's more "pythonic" - but please correct me if I'm wrong) which is why I'm not updating the values in place like the solution given here. I'm looking for something elegant because I don't like the idea of a long series of elif cases and would prefer something more generalised - I'm definitely an amateur so there are bound to be some types that I've never heard of.
I'm aware of collections.abc.Collection but I'm not sure how I'd use that to return a duplicate of the object (as opposed to just testing whether it's a member of this collection).