python赋值给循环中的元素列表

时间:2013-12-19 17:43:59

标签: python list loops object instance

这是一个有效的python行为吗?我认为最终结果应该是[0,0,0]并且id()函数应该在每次迭代时返回相同的值。如何使它成为pythonic,而不是使用枚举或范围(len(bar))?

bar = [1,2,3]
print bar
for foo in bar:
    print id (foo)
    foo=0
    print id(foo)
print bar

输出:

[1, 2, 3]
5169664
5169676
5169652
5169676
5169640
5169676
[1, 2, 3]

4 个答案:

答案 0 :(得分:21)

首先,你不能重新分配循环变量,你可以,但这不会改变你正在迭代的列表。因此设置foo = 0不会更改列表,只会更改局部变量foo(恰好包含每次迭代开始时迭代的值)。

接下来,像01这样的小数字在内部保存在一个小整数对象池中(这是一个CPython实现细节,不一定是这样!)那是在为foo分配0后,0的ID是相同的。 id基本上是池中整数对象[0, 0, 0]的id。

如果要在迭代时更改列表,则遗憾的是必须按索引访问元素。因此,如果您想保持输出相同,但最后有for i in range(len(bar)): print id(bar[i]) bar[i] = 0 print id(bar[i]) print bar ,则必须迭代索引:

{{1}}

否则,它实际上是不可能的,因为只要将列表的元素存储在变量中,就会有一个单独的引用,它与列表中存储的链接无关。由于大多数这些对象都是不可变的,并且在为变量赋值时创建了新对象,因此您无法获得列表对更新的引用。

答案 1 :(得分:3)

是的,你得到的输出是普通的Python行为。为foo分配新值会更改foo的ID,而不会更改bar中存储的值。

如果你只想要一个零列表,你可以这样做:

bar = [0] * len(bar)

如果你想做一些更复杂的逻辑,新的赋值取决于旧的值,你可以使用列表理解:

bar = [x * 2 for x in bar]

或者您可以使用map

def double(x):
    return x * 2

bar = map(double, bar)

答案 2 :(得分:0)

你实际上根本没有更改列表。 循环的第一件事是将bar [0]分配给foo(相当于foo = bar [0])。 foo只是对1的引用。然后你将另一个onject 0分配给foo。这改变了foo的引用为0.但是你没有改变bar [0]。记住,foo作为变量,引用bar [0],但是为foo分配另一个值/对象根本不会影响bar [0]。

答案 3 :(得分:0)

bar = [0 for x in bar]

答案很长:foo只是一个本地名称,重新绑定不会影响列表。 Python变量实际上只是关键:值对,而不是内存位置的符号名称。