我在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'一词?提前谢谢!
答案 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
中存储的值,请使用map
或list 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都是一个列表对象。