简体   繁体   中英

Python: append dictionary into dictionary list

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.

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}

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])
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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM