python列表变异(用于循环内vs范围(len))
为什么下面的代码不改变传入列表:python列表变异(用于循环内vs范围(len)),python,arrays,loops,for-loop,Python,Arrays,Loops,For Loop,为什么下面的代码不改变传入列表: def modify(listarg): for x in listarg: x=x*2 鉴于这确实会使其发生变异: def modify(listarg): for x in range(len(listarg)): listarg[x]=listarg[x]*2 第一个简单地将名为x的变量重新绑定到一个对象,该对象的值是当前列表元素值的两倍。它对列表没有任何作用 第二种方法通过直接指定给列表的元素来修改列表
def modify(listarg):
for x in listarg:
x=x*2
鉴于这确实会使其发生变异:
def modify(listarg):
for x in range(len(listarg)):
listarg[x]=listarg[x]*2
第一个简单地将名为
x
的变量重新绑定到一个对象,该对象的值是当前列表元素值的两倍。它对列表没有任何作用
第二种方法通过直接指定给列表的元素来修改列表
下面是修改列表的另一种方法:
def modify(listarg):
listarg[:] = [el * 2 for el in listarg]
在这里,
[:]
很重要;如果没有它,我们将创建一个新列表,而不是替换现有列表的内容。第一个列表只提供迭代变量(x
),本质上是for…in
使用内置的iter
函数。在第二种情况下,实际上是将值绑定到列表
for x in listarg:
x=x*2
上述代码可以看作:
i = iter(listarg)
x = i.next() # fetch first value
# this value then you double
# which won't effect the element
有关更多详细信息,请参阅此
这里的x
只是一个变量,它与您正在迭代的x
无关。就像在写:
def modify(listarg):
for x in listarg:
y=x*2
在第二段代码中,您试图修改列表本身。这是因为python中变量的命名方式(即内存的工作方式) 在第一种情况下,创建一个名为
x
的变量。随着时间的推移,您会反复为其指定列表中任何内容的值。从列表中为其指定一个值后,可以将其指定为该值的两倍。此时,您仍然在谈论x
——您已经从列表中读取了值并将其分配给x
,然后将两次x
的值分配给x
。让我们来看看这个代码:
def modify(listarg):
for x in listarg: # read a value from the list, and assign it as the value of the variable called x
x=x*2 # x is now 2x
要记住的关键是,内存中有一个空间存放名称,一个空间存放值(假设listarg=[1,2]
):
步骤名称边值边代码
listarg中x的1 x 1
2.x2x=x2
3.listarg中x的x 2
4.x4x=x2
因此,只有x
的值被更改。切勿使用listarg中的值
在第二种情况下,您直接访问listarg
的部分并更改其值:
步骤名称边值边代码
1.listarg[1,2]
x 0表示范围内的x(len(listarg))
2.x0
listarg[2,2]listarg[x]=listarg[x]*2
我将在这里停止跟踪执行情况,以表明我的观点:
您正在访问listarg
的第0个“隔间”(或索引),并修改分配给它的值。listarg[x]
保存的值正在更改,而不是某些其他变量的值(例如x
)
希望这有帮助如果x只是一个变量,与我正在迭代的x无关,那么为什么如果我打印x,我会得到我正在迭代的x?因为当你这样做时,你只是打印x
,而不是试图分配给它。当您尝试分配给它时,Python会自动区分您正在迭代的x
和您正在分配给它的x
。我一定是误解了for循环真正在迭代什么了。。。它似乎不是对列表对象的引用,而是一个副本。
def modify(listarg):
for x in listarg: # read a value from the list, and assign it as the value of the variable called x
x=x*2 # x is now 2x