不允许在Python中修改列表迭代器?

Rob*_*obW 8 python iterator list

简单的例子:

myList = [1, 2, 3, 4, 5]
for obj in myList:
  obj += 1
print myList
Run Code Online (Sandbox Code Playgroud)

版画

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

而:

myList = [1, 2, 3, 4, 5]
for index in range(0,len(myList)):
  myList[index] += 1
print myList
Run Code Online (Sandbox Code Playgroud)

版画

[1, 2, 3, 4, 5]
[2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)

结论:

  1. 可以使用全局列表访问列表来修改列表
  2. 列表项可以来代替使用迭代对象修改

我能找到的所有示例代码都使用全局列表访问器来修改列表.修改列表迭代器是否如此邪恶?

NPE*_*NPE 7

原因obj += 1并不是您所期望的,即此声明不会obj就地修改.相反,它计算新值,并重新绑定变量obj以指向新值.这意味着列表的内容保持不变.

在一般情况可能的,而使用过它迭代修改的列表for obj in myList.例如:

myList = [[1], [2], [3], [4], [5]]
for obj in myList:
  obj[0] += 1
print(myList)
Run Code Online (Sandbox Code Playgroud)

打印出:

[[2], [3], [4], [5], [6]]
Run Code Online (Sandbox Code Playgroud)

这和你的第一个例子之间的区别在于,这里列表包含可变对象,代码就地修改了这些对象.

请注意,也可以使用列表解析来编写循环:

myList = [val+1 for val in myList]
Run Code Online (Sandbox Code Playgroud)


Ade*_* YU 7

for obj in myList:每次迭代中,obj都是元素的(浅)副本myList.所以改变对于元素obj没有任何作用myList.

它与Perl 不同for my $obj (@myList) {}


sen*_*rle 6

我认为你误解了"迭代器对象"是什么.甲for环不是一个迭代器对象.对于所有意图和目的,这样的for循环:

myList = [0, 1, 2, 3, 4]
for x in myList:
    print x
Run Code Online (Sandbox Code Playgroud)

这样做(但更有效,更简洁):

i = 0
while i < len(myList)
    x = myList[i]
    print x
    i += 1
Run Code Online (Sandbox Code Playgroud)

所以你看,x一旦下一个循环开始,所做的任何更改都会丢失,因为值x会被列表中下一个项的值覆盖.

正如其他人所观察到的,它可以改变列表的价值,同时遍历它.(但不要改变它的长度!这就是你遇到麻烦的地方.)这样做的一个优雅方法如下:

for i, x in enumerate(myList):
    myList[i] = some_func(x)
Run Code Online (Sandbox Code Playgroud)

更新:了解在for循环中不进行复制也很重要.在上面的例子中,ix- 像Python中的所有变量一样 - 更像是C/C++中的指针.由于for循环的进展,obj 指出myList[0],myList[1]等等,反过来.和C/C++指针一样,当指针改变时,指向的对象的属性不会改变.但是也像C指针一样,你可以直接修改指向的东西,因为它不是副本.在C中,这是通过解除引用指针来完成的; 在Python中,这是通过使用可变对象来完成的.这就是为什么NPE的答案有效.如果ix甚至浅拷贝,这是不可能做到他做什么.

您无法直接更改ints的方式list(如NPE的答案),是因为ints不可变.一旦一个5对象被创建,没有什么可以改变它的价值.这就是为什么5在Python中传递指针是安全的 - 不会发生副作用,因为指向的东西是不可变的.