大家都同意for循环中的可迭代项只计算一次。因此,输出的f called只打印一次。
我正在努力弄明白的是,为什么我不能得到一个out-of-bound error?因为在评估时,长度等于100。
mylist = [x for x in range(100)]
def printmylist(thelist):
print("f called")
return thelist
for i, item in enumerate(printmylist(mylist)):
print(len(mylist))
del mylist[len(mylist) - i - 1]
f called 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51发布于 2016-03-18 22:15:41
在for循环中,使用列表的当前长度来评估要删除的位置。然后,从列表的末尾删除。所以你的循环只迭代50次。
如果您将print语句更改为显示i,您会发现它只在0到49之间计数。
发布于 2016-03-18 22:18:16
尽管print("f called")只被调用一次,但变量(在本例中称为iterable object,用于存储enumerate(printmylist(mylist))的估计值)会不时地更改其引用的set,因为您逐个删除了枚举。最初,您拥有所有的100个项目,但它是一个接一个地减少:
Note: len(mylist) - i - 1 = 99, delete index 99 -> 100 removed
1 2 3 ... 98 99 100 #len(mylist) = 100
^ <-- here is i = 0
Note: len(mylist) - i - 1 = 98, delete index 98 -> 99 removed
1 2 3 ... 98 99 #len(mylist) = 99
^ <-- here is i = 1
Note: len(mylist) - i - 1 = 97, delete index 97 -> 98 removed
1 2 3 ... 98 #len(mylist) = 98
^ <-- here is i = 2
... and so on此外,由于i将在循环的每一端都根据该变量进行检查(因此,iterable object ),因此您只能从50项中打印出100项。
来自the 的
:
表达式列表只计算一次;它应该产生一个可迭代的对象。为expression_list的结果创建迭代器。然后,对迭代器提供的每个项目执行一次套件,按索引升序排列的顺序为。使用分配的标准规则将每个项目依次分配给目标列表,然后执行套件。当项耗尽时(当序列为empty时立即出现),执行else子句中的套件(如果存在),并且loop 终止。
为了简单起见,假设你有
v = enumerate(printmylist(mylist)) #v is the iterable object虽然只计算一次,但每次删除一个项目时,v所指向的set都会发生变化,但i会迭代v。因此,i将不断增加,直到最终i = 50。
.
.
.
v = ... 50, i = 49
^ <-- here is i and is in v
v = ... 50 , i = 50 and is out from v
^ <-- no more item found没有更多的项目需要在边界之外进行评估。因此,您将获得以下结果:
100 99 ... 51而且不会越界。
More on how for works internally,包括它如何创建内部索引器,并根据每次终止值所指向的值对其进行检查。
https://stackoverflow.com/questions/36086548
复制相似问题