我已经声明了一个空列表,并且我想通过for
循环使用extend()
方法添加词典,但我最终得到的列表在其所有位置都具有相同的内容(相同字典)
这是代码:
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
如果我为extend()
更改了append()
,结果就更糟了。
答案 0 :(得分:3)
这是因为您每次都将相同的字典添加到列表中:实际上您只更改该字典的键/值,并再次添加该字典等等。
此外,通过使用extend
,您实际上将可迭代的元素添加到列表中。字典是 iterable :您遍历密钥。
所以你应该做的是(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)
我们也可以改进代码,例如,不是设置键值对,我们可以在构造字典时这样做。您使用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)
既然列表最初是空的,我们也可以使用 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]
答案 1 :(得分:1)
您的extend
或append
会将原始引用添加到task_data
,其内容会不断变化。相反,要么为task_data
创建一个新的空对象,要么附加您重复使用的副本的副本:
import copy
...
tasks_to_return.append(copy.copy(task_data))