6

我在 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' 术语到底是什么?提前致谢!

4

6 回答 6

9

这不起作用的原因是因为你误解了什么elem . 它不是对象本身,甚至称它为“变量”也不正确。

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

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

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

于 2012-08-02T20:54:18.107 回答
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(除其他外,如果列表在迭代时变得更长或更短会发生什么)?

于 2012-08-02T20:54:33.693 回答
3

当您为 name 分配一个新值时elem,您只需更改for循环中的本地绑定。如果要更改存储在lismap列表理解中的值,如下所示:

lis = [3 for elem in lis]

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

于 2012-08-02T20:52:39.433 回答
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]
于 2012-08-02T20:55:35.253 回答
1

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

Python 变量应被视为指向对象的标签。当您遍历一个不可变列表时,elem指向一个不可变对象,而不是指向列表中的那个位置,因此您不能修改原始列表。

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

于 2012-08-02T21:00:34.623 回答
0

这取决于 elem 的 type() 是什么。

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

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

于 2012-08-02T20:54:10.387 回答