python assign values to list elements in loop

匿名 (未验证) 提交于 2019-12-03 01:12:01

问题:

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))?

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] 

回答1:

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 = 0 will 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).

Next thing, small numbers, like 0 and 1 are 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 foo after you assign 0 to it. The id is basically the id of that integer object 0 in the pool.

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:

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.



回答2:

Yes, the output you got is the ordinary Python behavior. Assigning a new value to foo will change foo's id, and not change the values stored in 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:

def double(x):     return x * 2  bar = map(double, bar) 


回答3:

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.



回答4:

bar = [0 for x in bar] 

Long answer : foo is just a local name, rebinding does not impact the list. Python variables are really just key:value pairs, not symbolic names for memory locations.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!