What I'm trying to achieve is a dictionary containing sensors as keys and a list of dictionaries as values. The list of dictionary must be formatted {"value": xx,"timestamp": EpochTimeInMs}. The code is called cyclically to append new values to each sensor (key). The final result should be like this:
{
"temperature": [
{"value": 10,"timestamp": 1634336087000},
{"value": 11,"timestamp": 1634336088765}
],
"humidity": [
{"value": 90,"timestamp": 1634336087000},
{"value": 95,"timestamp": 1634336088765}
]
}'
To do so, I've tried this code:
import time
####################
my_sensors = ["temperature", "humidity"]
my_dict = {}.fromkeys(my_sensors, [])
print(my_dict)
val_template = ["value", "timestamp"]
my_val = {}.fromkeys(val_template)
my_val["timestamp"] = int(time.time()*1000)
print(my_val)
#temperature
my_val["value"] = 1234
print(my_val)
my_dict['temperature'].append(my_val.copy())
#humidity
my_val["value"] = 4321
print(my_val)
my_dict['humidity'].append(my_val.copy())
print(my_dict)
But each append seems to proceed to all keys. Here is the result from terminal:
{'temperature': [], 'humidity': []}
{'value': None, 'timestamp': 1651676483130}
{'value': 1234, 'timestamp': 1651676483130}
{'value': 4321, 'timestamp': 1651676483130}
{'temperature': [{'value': 1234, 'timestamp': 1651676483130}, {'value': 4321, 'timestamp': 1651676483130}], 'humidity': [{'value': 1234, 'timestamp': 1651676483130}, {'value': 4321, 'timestamp': 1651676483130}]}
Some help would be much appreciated.
CodePudding user response:
Appending to one list seems to appends to all lists because they are all the same list! You can check this by id(my_dict['humidity']) == id(my_dict['temperature'])
, which gives True
.
You need to create a new list for every key, so do that:
my_dict = {s: [] for s in my_sensors}
CodePudding user response:
import time
my_sensors = ["temperature", "humidity"]
my_dict = {"temperature":[],"humidity":[]}
val_template = ["value", "timestamp"]
my_val = {"value": None, "timestamp": None}
my_val["timestamp"] = int(time.time()*1000)
#temperature
new_dict = my_val.copy()
new_dict["value"] = 1234
my_dict['temperature'].append(new_dict)
#humidity
new_dict = my_val.copy()
new_dict["value"] = 4321
my_dict['humidity'].append(new_dict)
print(my_dict)
Python internally uses pointers. Hence, the empty list ([]) in the fromkeys() function is a single list that is provided by default to each key.
CodePudding user response:
From https://docs.python.org/3/library/stdtypes.html:
classmethod fromkeys(iterable[, value])
Create a new dictionary with keys from iterable and values set to value. fromkeys() is a class method that returns a new dictionary. value defaults to None. All of the values refer to just a single instance,
so it generally doesn’t make sense for value to be a mutable object such as an empty list. To get distinct values, use a dict comprehension instead.
Important to note the statement : "All of the values refer to just a single instance"
You can verify it by getting the address of the values:
print(id(my_dict['temperature']))
print(id(my_dict['humidity']))
2606880003968
2606880003968
You should use dict comprehension to create your dictionary like:
my_dict = dict([(sensor, []) for sensor in my_sensors])