python为循环中的列表元素赋值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20688324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
python assign values to list elements in loop
提问by Chris
Is this a valid python behavior? I would think that the end result should be [0,0,0] and the id() function should return identical values each iteration. How to make it pythonic, and not use enumerate or range(len(bar))?
这是有效的python行为吗?我认为最终结果应该是 [0,0,0] 并且 id() 函数应该在每次迭代中返回相同的值。如何使它成为 pythonic,而不使用 enumerate 或 range(len(bar))?
bar = [1,2,3]
print bar
for foo in bar:
print id (foo)
foo=0
print id(foo)
print bar
output:
输出:
[1, 2, 3]
5169664
5169676
5169652
5169676
5169640
5169676
[1, 2, 3]
采纳答案by poke
First of all, you cannot reassign a loop variable—well, you can, but that won't change the list you are iterating over. So setting foo = 0will not change the list, but only the local variable foo(which happens to contain the value for the iteration at the begin of each iteration).
首先,你不能重新分配一个循环变量——好吧,你可以,但这不会改变你正在迭代的列表。所以设置foo = 0不会改变列表,而只会改变局部变量foo(它恰好包含每次迭代开始时的迭代值)。
Next thing, small numbers, like 0and 1are internally kept in a pool of small integer objects (This is a CPython implementation detail, doesn't have to be the case!) That's why the ID is the same for fooafter you assign 0to it. The id is basically the id of that integer object 0in the pool.
接下来,小数字,比如0和1被内部保存在一个小整数对象池中(这是一个 CPython 实现细节,不一定是这种情况!)这就是为什么foo分配0给它后ID 是相同的。id 基本上0是池中该整数对象的 id 。
If you want to change your list while iterating over it, you will unfortunately have to access the elements by index. So if you want to keep the output the same, but have [0, 0, 0]at the end, you will have to iterate over the indexes:
如果您想在迭代时更改列表,不幸的是,您将不得不通过索引访问元素。因此,如果您想保持输出相同,但[0, 0, 0]在最后,您将不得不遍历索引:
for i in range(len(bar)):
print id(bar[i])
bar[i] = 0
print id(bar[i])
print bar
Otherwise, it's not really possible, because as soon as you store a list's element in a variable, you have a separate reference to it that is unlinked to the one stored in the list. And as most of those objects are immutable and you create a new object when assigning a new value to a variable, you won't get the list's reference to update.
否则,这是不可能的,因为一旦将列表的元素存储在变量中,就会有一个单独的引用,该引用与存储在列表中的元素没有链接。由于这些对象中的大多数是不可变的,并且您在为变量分配新值时创建了一个新对象,因此您不会获得要更新的列表引用。
回答by Kevin
Yes, the output you got is the ordinary Python behavior. Assigning a new value to foowill change foo's id, and not change the values stored in bar.
是的,您得到的输出是普通的 Python 行为。分配一个新值foo将改变 foo 的 id,而不是改变存储在bar.
If you just want a list of zeroes, you can do:
如果你只想要一个零列表,你可以这样做:
bar = [0] * len(bar)
If you want to do some more complicated logic, where the new assignment depends on the old value, you can use a list comprehension:
如果你想做一些更复杂的逻辑,新赋值依赖于旧值,你可以使用列表理解:
bar = [x * 2 for x in bar]
Or you can use map:
或者你可以使用map:
def double(x):
return x * 2
bar = map(double, bar)
回答by Twisted Meadow
you actually didnt change the list at all. the first thing for loop did was to assign bar[0] to foo(equivalent to foo = bar[0]). foo is just an reference to 1. Then you assign another onject 0 to foo. This changed the reference of foo to 0. But you didnt change bar[0]. Remember, foo as a variable, references bar[0], but assign another value/object to foo doesn't affect bar[0] at all.
您实际上根本没有更改列表。for 循环所做的第一件事是将 bar[0] 分配给 foo(相当于 foo = bar[0])。foo 只是对 1 的引用。然后您将另一个对象 0 分配给 foo。这将 foo 的引用更改为 0。但您没有更改 bar[0]。请记住,foo 作为变量,引用 bar[0],但为 foo 分配另一个值/对象根本不会影响 bar[0]。
回答by bruno desthuilliers
bar = [0 for x in bar]
Long answer : foois just a local name, rebinding does not impact the list. Python variables are really just key:value pairs, not symbolic names for memory locations.
长答案:foo只是一个本地名称,重新绑定不会影响列表。Python 变量实际上只是键值对,而不是内存位置的符号名称。

