简体   繁体   中英

Removing last element of a list in Python fails

I'm trying to remove the last element of a list in Python:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children']:
  di['children'].remove(el)

What I'd expect is

print di
{'a': 3, 'children: []}

But what I get is

print di
{'a': 3, 'children': [{'c': 6}]}

Does anybody have an idea what's going wrong?

As everyone else has explained, you can't modify a list while iterating over it.

You can modify a list while iterating over a copy of it, but it's probably better to just generate a new filtered list:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = [el for el in di['children'] if el not in di['children']]

Why is this better? Well, it means you're avoiding mutating the list, which makes your code easier to reason about, easier to trace through, usually easier to write, and often faster and more space-efficient. The fact that you don't have to worry about mutating-while-iterating problems is a perfect example of the "easier to reason about" part.

In some cases, it does turn out to be harder to write, or slower, or less space-efficient, which is why this is just a guideline rather than a hard rule. But it's always at least worth thinking "can I rewrite this as an immutable filter instead of a mutator", even if the answer may sometimes turn out to be "no".

Also really, isn't your algorithm guaranteed to be equivalent to just emptying the whole thing out? In that case:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
di['children'] = []

You shouldn't modify the list as you iterate it. You should instead iterate over a copy. See the python docs .

Try this...

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]}
for el in di['children'][:]:
    di['children'].remove(el)

You are modifying a list as you are iterating over it - when you remove the first entry, the second entry becomes the first and the end of the list has been reached. Instead, use:

del di["children"][:]

This will preserve the original list (unlike di["children"] = [] ) so if you have other references to them they will also reflect the truncation.

You can only remove elements in the loop when you going through a list in backward direction.

So I think just wrap di['children'] in reversed() iterator like this

for el in reversed(di['children']):

It's because removing element causes changing numeration of elements, and all following elements will have number minus 1. But, if you going backward, you shouldn't care about indexes of following elements, just about elements before deleted.

You're modifying the list as you iterate over it, which is a bad idea.

Try iterating over a copy of the list, while removing the elements from the original.

del di['children'][1]

删除列表中的最后一个元素。

 for i in di:
    if type(di[i])==list:
       di[i]=[]

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