简体   繁体   English

将元素插入字典列表

[英]insert an element into a list of dictionaries

I have declared an empty list and I want to append dictionaries through a for loop by using the extend() method, but I end with a list with the same content in all its positions (the same dictionary) 我已经声明了一个空列表,我想通过使用extend()方法通过for循环追加字典,但是我最后得到一个列表,该列表的所有位置都具有相同的内容(相同的字典)

This is the code: 这是代码:

def get_tasks(self, actor, task_state):
    tasks = Task.objects.filter(actor=actor.id, state=task_state)
    tasks_to_return = []
    task_data = {}

    for task in tasks:
        task_data['name'] = getattr(task, 'name')
        task_data['description'] = getattr(task, 'description')
        task_data['start_date'] = getattr(task, 'start_date')
        task_data['finish_date'] = getattr(task, 'finish_date')
        task_data['situation'] = task.get_situation()
        tasks_to_return.extend(task_data)

    return tasks_to_return

If I change extend() for append() , the result is even worst. 如果我将extend()更改为append() ,结果将更糟。

That is because you each time add the same dictionary to the list: indeed you only change the key/values of that dictionary, and add that dictionary a second time, etc. 那是因为您每次都将相同的词典添加到列表中:实际上,您只更改了该词典的键/值,然后第二次添加了该词典,依此类推。

Furthermore by using extend , you actually add a iterable of elements to a list. 此外,通过使用extend ,您实际上将一个可迭代的元素添加到列表中。 A dictionary is an iterable : you iterate over the keys. 字典是可迭代的 :您遍历键。

So what you should do is (1) construct a new dictionary each time, and (2) use append instead of extend: 因此,您应该做的是(1)每次构造一个新字典,(2)使用append而不是extend:

for task in tasks:
    task_data = {}
    task_data['name'] = getattr(task, 'name')
    task_data['description'] = getattr(task, 'description')
    task_data['start_date'] = getattr(task, 'start_date')
    task_data['finish_date'] = getattr(task, 'finish_date')
    task_data['situation'] = task.get_situation()
    tasks_to_return.append(task_data)

We can also improve the code, for instance instead of setting the key-value pairs, we can do this at the construction of the dictionary. 我们还可以改进代码,例如,代替设置键值对,我们可以在构建字典时做到这一点。 You use getattr(..) , but this is not necessary here: we can use task.name instead of getattr(task, 'name') , so a more elegant approach is probably: 您可以使用getattr(..) ,但这不是必需的:我们可以使用task.name代替getattr(task, 'name') ,因此一种更优雅的方法可能是:

tasks_to_return = []
task_data = {}
for task in tasks:
    task_data = { 'name': task.name, 'description': task.description, 'start_date': task.start_date, 'finish_date': task.finish_date, 'situation': task.situation }
    tasks_to_return.append(task_data)

Now since the list is initially empty, we can also use list comprehension : 现在,由于列表最初是空的,因此我们还可以使用列表理解

tasks_to_return = [ {
        'name': task.name,
        'description': task.description,
        'start_date': task.start_date,
        'finish_date': task.finish_date,
        'situation': task.situation
    } for task in tasks]

Your extend or append adds the original reference to task_data , whose contents you keep changing. 您的extendappend将原始引用添加到task_data ,您不断更改其内容。 Instead, either make a new empty object for task_data , or append a copy of the one you reuse: 相反,要么为task_data创建一个新的空对象,要么附加一个您要重用的对象的副本:

import copy
...
    tasks_to_return.append(copy.copy(task_data))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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