在 Python 中,只要一个“容器”(如 list、dict、set 等)正在被遍历(for 循环、迭代器),就不应该在遍历过程中对它做“结构性修改

在这里插入图片描述

正确操作:遍历副本或用新容器

遍历副本时注意浅拷贝 深拷贝的问题
深拷贝,浅拷贝
在这里插入图片描述

字典举例

d.items() 返回的是字典中元素的实时视图(view),d变了也会变

d = {
    "a": 1,
    "b": 2,
    "c": 3,
}

for k, v in d.items():
    print("当前处理:", k)
    if k == "b":
        d.pop(k)
"""
当前处理: b
Traceback (most recent call last):
  File "D:\zhouj\Documents\Pythontest\flasky\hello.py", line 7, in <module>
    for k, v in d.items():
RuntimeError: dictionary changed size during iteration
"""

在这里插入图片描述

list(d.items())

d = {
    "a": 1,
    "b": 2,
    "c": 3,
}

for k, v in list(d.items()):
    print("当前处理:", k)
    if k == "b":
        d.pop(k)
print(d)
"""
当前处理: c
当前处理: b
当前处理: a
{'c': 3, 'a': 1}
"""

在这里插入图片描述

d = {"a": [1], "b": [5], "c": 3}

lst = list(d.items())
print(lst)
d["a"] = [3]
d["b"].append(5)
print(d)
print(lst)
"""
原来的 [1] 对象没有改变,只是 d["a"] 不再引用它,因为 d["a"] 被重新赋值指向新列表
lst仍然引用
[('c', 3), ('a', [1]), ('b', [5])]
{'c': 3, 'a': [3], 'b': [5, 5]}
[('c', 3), ('a', [1]), ('b', [5, 5])]
"""

集合举例

s = {1, 2, 3}

for x in s:
    s.remove(x)
"""
Traceback (most recent call last):
  File "D:\zhouj\Documents\Pythontest\flasky\hello.py", line 3, in <module>
    for x in s:

"""

在这里插入图片描述

列表举例

for x in lst, lst每次都是最新的,对lst的修改,下次循环会生效,lst 始终是最新的列表对象
访问的是最新的 lst,所以你看到的 lst 总是最新状态
for x in lst本质是
it = iter(lst) x= next(it),
next(it) 每次访问 lst[x] → 所以看到的是最新列表内容
迭代器返回元素时,是根据 当前指针位置 取元素
迭代器不会重新计算长度,也不会跳到“末尾”去停止,迭代器内部的指针每次 +1,会在调用 next(it) 时检查有没有元素,:
如果迭代器内部指针 >= 当前列表长度 → StopIteration → 循环结束
如果迭代器内部指针 < 当前列表长度 → 返回元素
指针不管列表长度变化 → 可能跳过元素或重复处理
简单理解就是每次取lst[i],i索引每次+1,但lst长度动态变化,lst始终是最新的列表对象

lst = [1, 2, 4, 6]

for x in lst:
    if x % 2 == 0:
        lst.remove(x)

print(lst)

"""
[1, 4]
"""

在这里插入图片描述

在这里插入图片描述

更多推荐