开发者

Why does list.remove() not behave as one might expect?

开发者 https://www.devze.com 2023-03-31 06:39 出处:网络
from pprint import * sites = [[\'a\',\'b\',\'c\'],[\'d\',\'e\',\'f\'],[1,2,3开发者_JAVA技巧]] pprint(sites)
from pprint import *

sites = [['a','b','c'],['d','e','f'],[1,2,3开发者_JAVA技巧]]

pprint(sites)

for site in sites:
        sites.remove(site)

pprint(sites)

outputs:

[['a', 'b', 'c'], ['d', 'e', 'f'], [1, 2, 3]]
[['d', 'e', 'f']]

why is it not None, or an empty list [] ?


It's because you're modifying a list as you're iterating over it. You should never do that.

For something like this, you should make a copy of the list and iterate over that.

for site in sites[:]:
    sites.remove(site)


Because resizing a collection while iterating over it is the Python equivalent to undefined behaviour in C and C++. You may get an exception or subtly wrong behaviour. Just don't do it. In this particular case, what likely happens under the hood is:

  • The iterator starts with index 0, stores that it is at index 0, and gives you the item stored at that index.
  • You remove the item at index 0 and everything afterwards is moved to the left by one to fill the hole.
  • The iterator is asked for the next item, and faithfully increments the index it's at by one, stores 1 as the new index, and gives you the item at that index. But because of said moving of items caused by the remove operation, the item at index 1 is the item that started out at index 2 (the last item).
  • You delete that.
  • The iterator is asked for the next item, but signals end of iteration as the next index (2) is out of range (which is now just 0..0).


Normally I would expect the iterator to bail out because of modifying the connected list. With a dictionary, this would happen at least.

Why is the d, e, f stuff not removed? I can only guess: Probably the iterator has an internal counter (or is even only based on the "fallback iteration protocol" with getitem).

I. e., the first item yielded is sites[0], i. e. ['a', 'b', 'c']. This is then removed from the list.

The second one is sites[1] - which is [1, 2, 3] because the indexes have changed. This is removed as well.

And the third would be sites[2] - but as this would be an index error, the iterator stops.

0

精彩评论

暂无评论...
验证码 换一张
取 消