For循环语句评估

时间:2016-03-18 14:08:46

标签: python for-loop iteration

它同意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

2 个答案:

答案 0 :(得分:2)

for循环中,使用列表的当前长度来评估要删除的位置。并且,您从列表的末尾删除。所以你的循环只迭代50次。

如果您更改print语句以显示i,您会发现它只会从0到49进行计数。

答案 1 :(得分:2)

虽然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个项目。

  

来自 Python for statement documentation

     

表达式列表的评估一次;它应该产生一个可迭代的   宾语。为expression_list的结果创建了一个迭代器。   然后,对于由提供的每个项目,一次执行该套件   迭代器,按升序索引。每个项目依次是   使用分配的标准规则分配给目标列表,   然后套件被执行。 当项目耗尽时(即   当序列为空时立即,else子句中的套件,   如果存在,则执行,loop 终止

为了简化,假设你有

v = enumerate(printmylist(mylist)) #v is the iterable object

虽然只评估过一次,但每次删除项目时,set所指向的v都会发生变化,但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,包括它如何创建内部索引器并每次都根据终止值指向的值进行检查。