Home > Mobile >  Python: append dictionary into dictionary list
Python: append dictionary into dictionary list

Time:05-05

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])
  • Related