关于for循环中实际发生的事情:
根据Python for语句文档:
表达式列表被执行一次,它应该返回一个可迭代对象。为expression_list
的结果创建一个迭代器。然后按照索引递增的顺序每次为迭代器提供的每个项目执行一次套件。每个项目依次使用分配的列表目标进行分配,然后执行套件。当项用尽时(即序列为空时)执行else子句中的套件(如果存在),并且loop
就终止了。
我认为最好通过一个图示来展示。
现在,假设您有一个像这样的iterable对象
(例如list
):
out = [a, b, c, d, e, f]
当您执行
for x in out
时,会创建一个内部索引器,其运行方式如下(我用符号
^
来说明):
[a, b, c, d, e, f]
^ <
通常情况下发生的是:当您完成循环的一个周期时,索引器向前移动,如下所示:
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
正如您所看到的,索引器会一直向前移动到列表末尾,无论列表发生了什么!因此,当您执行remove时,内部会发生以下情况:
[a, b, c, d, e, f]
^ <-- here is the indexer
[b, c, d, e, f]
^ <-- here is the indexer
[b, c, d, e, f]
^ <-- here is the indexer
[c, d, e, f]
^ <-- here is the indexer
[c, d, e, f]
^ <-- here is the indexer
[c, d, f]
^ <-- here is the indexer
注意,这里只有3个循环,而不是原始列表中的6个循环(!!)。这就是为什么在每个循环中删除一个元素后,留下一半的len
,因为这是完成循环所需的周期数。
如果你想清空列表,只需要执行:
if (out != []):
out.clear()
或者,另一种方法是逐个删除元素,你需要 反过来 - 从尾部到头部 进行操作。使用 reversed
:
for x in reversed(out):
out.remove(x)
现在,为什么会有reversed
方法?如果索引器一直往前移,那么每个周期元素的数量都会减少一个,reversed
也不应该起作用,对吗?
不,不是这样的,
因为reversed
方法改变了内部索引器的工作方式!使用reversed
方法时发生的情况是,将内部索引器向后移动(从末尾开始),而不是向前移动。
为了举例说明,这是通常发生的情况:
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e, f]
^ <-- here is the indexer
因此,当您每个周期执行一次删除操作时,它不会影响索引器的工作:
[a, b, c, d, e, f]
^ <-- here is the indexer
[a, b, c, d, e]
^ <-- here is the indexer
[a, b, c, d, e]
^ <-- here is the indexer
[a, b, c, d]
^ <-- here is the indexer
[a, b, c, d]
^ <-- here is the indexer
[a, b, c]
^ <-- here is the indexer
[a, b, c]
^ <-- here is the indexer
[a, b]
^ <-- here is the indexer
[a, b]
^ <-- here is the indexer
[a]
^ <-- here is the indexer
[a]
^ <-- here is the indexer
[]
^ <-- here is the indexer
希望这个插图能帮助你理解内部发生了什么...