我正在尝试删除Python中列表的最后一个元素:
di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children']:
di['children'].remove(el)
我期待的是
print di
{'a': 3, 'children: []}
但我得到的是
print di
{'a': 3, 'children': [{'c': 6}]}
有人知道出了什么问题吗?
答案 0 :(得分:11)
正如其他人所解释的那样,你无法在迭代时修改列表。
您可以在迭代其副本时修改列表,但最好只生成一个新的过滤列表:
di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = [el for el in di['children'] if el not in di['children']]
为什么这样更好?好吧,这意味着你要避免改变列表,这使你的代码更易于推理,更容易追踪,通常更容易编写,而且通常更快,更节省空间。事实上,您不必担心迭代变异问题,这是“更容易推理”部分的一个完美示例。
在某些情况下,它确实更难写,或更慢,或更节省空间,这就是为什么这只是一个指导而不是硬规则。但它始终至少值得思考“我可以将其重写为不可变过滤器而不是变换器”,即使答案有时可能变为“不”。
另外,您的算法是否保证等同于将整个事情清空?在那种情况下:
di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = []
答案 1 :(得分:6)
您不应在迭代时修改列表。你应该迭代一个副本。请参阅python docs。
试试这个......
di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children'][:]:
di['children'].remove(el)
答案 2 :(得分:6)
当您迭代它时,您正在修改列表 - 当您删除第一个条目时,第二个条目成为第一个条目,并且已到达列表的末尾。相反,使用:
del di["children"][:]
这将保留原始列表(与di["children"] = []
不同),因此如果您有其他引用,它们也会反映截断。
答案 3 :(得分:4)
当您向后浏览列表时,只能删除循环中的元素。
所以我认为只需将di ['children']包装在reverse()迭代器中就像这样
for el in reversed(di['children']):
这是因为删除元素导致元素的编号变化,并且所有后续元素的数字减1.但是,如果你向后,你不应该关心以下元素的索引,只关心删除之前的元素。
答案 4 :(得分:2)
你在迭代它时修改列表,这是一个坏主意。
尝试迭代列表的副本,同时从原始列表中删除元素。
答案 5 :(得分:2)
del di['children'][1]
删除列表中的最后一个元素。
答案 6 :(得分:0)
for i in di:
if type(di[i])==list:
di[i]=[]