Python如何迭代for循环?

时间:2012-08-02 20:46:47

标签: python loops for-loop

我在Python上尝试了以下代码,这就是我得到的: 似乎我尝试通过改变elem来对迭代进行许多更改,但它不起作用。

lis = [1,2,3,4,5]
for elem in lis:
    elem = 3

print lis
[1, 2, 3, 4, 5]

但是,如果迭代是具有自己的方法的对象(如列表),则可以在for循环中修改它们。

lis = [[1],[2]]
for elem in lis:
    elem.append(8)

print lis
    [[1, 8], [2, 8]]

for循环中究竟是什么'elem'一词?提前谢谢!

6 个答案:

答案 0 :(得分:9)

这不起作用的原因是因为您误解了elem 的内容。它不是对象本身,将它称为“变量”甚至都不正确。

这是一个名称,有点像标签,指向对象。如果您只是直接分配它,那么您只需覆盖该名称以指向其他内容。但是,您仍然拥有对列表的原始引用,因此为elem分配不同的值不会修改lis本身。

现在,在这种情况下,由于elem指向的所有对象都是整数,因此你根本无法更改 - 因为整数(以及许多其他类型,像字符串或元组一样不可变。这意味着,简单地说,一旦创建了对象,它就无法修改。它与它们是否“有方法”无关(所有Python对象都包含方法,包括整数),而与它们是否是不可变的无关。

但是,某些对象是可变,这意味着它们可以更改。列表是此类对象的示例。在第二个示例中,elem是一个引用lis中包含的 list 对象的名称,它们本身是可变的。这就是为什么就地修改它们(使用.append().remove()等)可以正常工作。

答案 1 :(得分:5)

elem循环中的for变量是每次迭代时对当前对象的引用。改变它不会做任何事情;它只会改变变量elem的值,并且无论如何都会在下一次循环时改变它。要实际更改列表中元素的值,您需要对列表的引用和要更改的元素的索引,并且您没有后者。

所以你想要做的是这样的事情:

for index, elem in enumerate(lis):
    lis[index] = 3

这样,元素的值为elem,列表中的位置为index。它可以避免您不断编写lis[index]来获取值,但您仍必须这样做才能更改元素。

你也可以这样做:

for index in xrange(len(lis)):
    lis[index] = 3

然而,在大多数情况下,这被认为是非Pythonic(除其他外,如果列表在迭代时变得更长或更短,会发生什么?)

答案 2 :(得分:3)

为名称elem分配新值时,只需更改for循环中的本地绑定即可。如果您想更改lis中存储的值,请使用maplist comprehension,如下所示:

lis = [3 for elem in lis]

但是,您可以修改elem的属性(或调用这样做的方法),就像您可以修改任何其他值一样。

答案 3 :(得分:3)

在这里,您实际上是在修改第二个示例中的列表对象。在第一个示例中,您没有修改数字,而是要替换它。对于Python的新用户来说,这可能是一个复杂的细微差别。

检查出来:

>>> x = 1
>>> id(x)
4351668456
>>> x = 2
>>> id(x)
4351668432

id返回对象的标识符。如您所见,x的对象会改变这两个时间。

>>> y = [1]
>>> id(y)
4353094216
>>> y.append(2)
>>> id(y)
4353094216

在这里,我修改了列表,因此列表仍然是原始对象y

所以,所有这些意味着当你在做elem = 3时,它不会修改它,它正在取代它。到现在为止,它已不再与列表相关联。

这是你可以做你想做的事情的方法之一。这会抓取索引,然后修改列表,而不是数字。

lis = [1,2,3,4,5]
for idx, elem in enumerate(lis):
    lis[idx] = 3

print lis
[1, 2, 3, 4, 5]

答案 4 :(得分:1)

在你的第一个例子中,你试图修改一个整数,它是不可变的(就像字符串一样)。

Python变量应该被视为指向对象的标签。当迭代一个无条件列表时,elem指向一个不可变对象,而不是列表中的那个位置,因此你无法修改原始列表。

在第二种情况下,elem指向可以修改的对象,因此您可以看到原始列表已更改。

答案 5 :(得分:0)

这取决于elem的类型()。

在你的第一种情况下,每个elem都是一个int对象,它确实可以改变它。当您说:elem = 3时,您正在更改临时对象,而不是列表中的项目。

在第二种情况下,每个elem都是一个列表对象。