TL;DR: use {k: v for k, v in zip(names, data)}
where names
is a list of names for your values, or dict(zip(names, data))
(which I personally find less readable).
There are two sources of complexity in your code (and I mean human-percieved complexity, not computational complexity):
details, which hide the big picture of what's going on;
the fact that the values in data
have names, and those names depend on the order of the data
list.
The 1st is easy to solve, just split everything into functions, each of which does one thing only, on the appropriate level of abstraction.
The 2nd is more tricky, since even if you define a tuple of names for your values, there's still an implicit relationship left between the order of values in the frame['data']
string, and the order of values in your tuple. Those kinds of implicit relations are not obvious to someone who doesn't know as much as you do about your code (i.e. to everyone else).
Imagine that the structure of the string in frame['data']
changes. Then, your code will be broken, probably in a very unobvious way, and in a totally unrelated place. It's stuff like this that creates spaghetti code.
I don't know where the frame
comes from, so it's hard to give a good advice here. In general, you can pack the frame
and the tuple of names into another data structure where you create the frame
, and never use the frame
alone. Or, make the tuple of names a part of frame
. In any case, you want to keep them bound together.
Or, you may encapsulate frame
's contents in a class. This class can have a method which returns data in the appropriate dictionary form. The order of the names can be a private variable, encapsulated inside the class.
If I had to stay with frame
as it is, I'd do something like this (the names of the functions can be chosen much better, I don't know enough context to come up with good names):
NAMES = (
'state',
'flow_rate',
'operating_hours',
)
def get_cat_data(frame):
data = _get_data(frame)
base = _data_to_dict(data, NAMES)
base.update(_get_xbee_address(frame))
return base
def _get_data(frame):
return frame['data'].split(';')
def _data_to_dict(data, names):
return {k: v for k, v in zip(names, data)}
def _get_xbee_address(frame):
return {'xbee_address': '\x00' + frame['source_addr']} #consider naming the string literal and using a constant instead
I hope this helps.