我知道在python中,当你将两个列表等同时,你实际上并没有在内存中复制该列表,只是在内存中创建一个新的alais 指向到该列表。像
这样的东西listA = [1,2,3]
listB = listA
listB[0] = 5
print(listA) #prints [5,2,3]
对我来说非常有意义。
我也知道你可以在for循环中修改可变类型(如列表),而对于其他类型(如整数),你不能,并且必须修改原始列表。例如
listA = [1,2,3]
listB = [4,5,6]
for Int in listA:
Int +=1
print(listA) #doesn't work, prints [1,2,3]
for List in [listA,listB]:
List[2] = 100
print(listA) #works, prints [1,2,100]
当我试图将这两个原则结合起来时,我的问题出现了。这是我尝试做的一个例子:
x = [1.2345,0.543895,0.0]
y = [2,3,4]
z = [65.34,3.248578493,1.11111]
for coord in [x,y,z]:
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
print(x,y,z) #prints unmodified numbers
在这个例子中,' coord'是一个列表,因此我应该能够修改它,就像我之前的例子中的listA一样,但我不能。我必须使用枚举:
x = [1.2345,0.543895,0.0]
y = [2,3,4]
z = [65.34,3.248578493,1.11111]
coordlist = [x,y,z]
for idx,coord in enumerate(coordlist):
coordlist[idx] = [round(item,3) for item in coord]
print(coordlist)
为什么我的原始尝试不起作用?
答案 0 :(得分:0)
' COORD'是一个列表,因此我应该能够修改它......
几乎,但不完全。 coord
是一个变量,每次迭代依次存储对每个原始列表的引用。
rounded_coord
也是一个存储对新列表的引用的变量。
现在,执行coord = rounded_coord
会使变量coord
指向与rounded_coord
相同的引用。这意味着coords
的原始内容在coord
指向更改的引用时将保持不变。
示例:
>>> x = [1, 2, 3, 4, 5]
>>> for l in [x]:
... print(id(l))
... new_l = [1]
... l = new_l
... print(id(l))
...
4309421160
4309421592
顺便说一下,id
打印一个10位数字,表示变量指向的引用。您可以看到在开始时与结尾时,l
中存储的引用会发生变化。
答案 1 :(得分:0)
问题是赋值永远不会改变。它只是创建一个新的引用,或者重新分配引用(这就是你正在做的事情)。您必须使用mutator方法,例如:
In [1]: x = [1.2345,0.543895,0.0]
...: y = [2,3,4]
...: z = [65.34,3.248578493,1.11111]
...: for coord in [x,y,z]:
...: coord[:] = [round(item,3) for item in coord]
...: print(x,y,z)
...:
[1.234, 0.544, 0.0] [2, 3, 4] [65.34, 3.249, 1.111]
因此,即使coord[:] = [round(item,r) for item in cord]
看起来像一样,也不是常规作业。调用mutator方法是语法糖,准确地说__setitem__
:
In [2]: coord
Out[2]: [65.34, 3.249, 1.111]
In [3]: coord.__setitem__(slice(None,None), ['foo','bar','baz'])
In [4]: coord
Out[4]: ['foo', 'bar', 'baz']
同样地,List[0] = 100
不是作业,它是语法糖:
In [6]: List
Out[6]: [1, 2, 3]
In [7]: List[0] = 99
In [8]: List
Out[8]: [99, 2, 3]
In [9]: List.__setitem__(0, 'foo')
In [10]: List
Out[10]: ['foo', 2, 3]
你不能修改不可变类型,因为根据定义,它们没有mutator方法,即使有看起来的操作像mutator方法一样:
x = 10
x += 10 # looks like a mutator method but actually assigns a new object to x
注意,str
类似于列表。您可以对其进行切片,但相应的mutator方法不存在:
In [17]: s = 'abcdefg'
In [18]: s[:3]
Out[18]: 'abc'
In [19]: s.__getitem__(slice(0,3))
Out[19]: 'abc'
In [20]: s.__setitem__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-20-44ee26769121> in <module>()
----> 1 s.__setitem__
AttributeError: 'str' object has no attribute '__setitem__'
答案 2 :(得分:0)
在你的例子中:
x = [1.2345,0.543895,0.0]
y = [2,3,4]
z = [65.34,3.248578493,1.11111]
for coord in [x,y,z]:
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
print(x,y,z) #prints unmodified numbers
coord
不是列表 - 它是指向ad-hoc创建的[x, y, z]
列表中列表的指针。由于这是一个相对简单的例子,这里是如何在没有循环的情况下解压缩:
coord = x
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
coord = y
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
coord = z
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
看到它的问题?
如果您真的想要更改元素本身,则必须在替换时通过其容器列表中的索引引用它(因为您已注意到它与enumerate
一起使用)或替换值到位:
for coord in [x,y,z]:
coord[:] = [round(item,3) for item in coord] # assuming not overriden __setslice__()
答案 3 :(得分:0)
您的第一个示例无效,因为coord
仅是对x
,y
和z
列表的引用。当您重新分配coord
时,您将覆盖原始引用并设置coord
以引用新的列表对象。
换句话说,coord
不是每个列表的指针。相反,它只是一个参考。当您重新分配coord
时,您将失去原始参考。
您可以通过改变列表对象coord
引用来解决此问题:
>>> x = [1.2345, 0.543895, 0.0]
>>> y = [2, 3, 4]
>>> z = [65.34, 3.248578493, 1.11111]
>>>
>>> for coord in [x, y, z]:
coord[:] = [round(item,3) for item in coord]
>>> x
[1.234, 0.544, 0.0]
>>> y
[2, 3, 4]
>>> z
[65.34, 3.249, 1.111]
>>>
答案 4 :(得分:0)
在所有情况下,循环变量只是被循环的东西中每个元素的别名。
您的第二个示例中coord
的工作方式与您希望的相同,但第三个示例中的List
并不是,在第二个示例中,您正在改变coord
指向的列表元素,因此实际更新了基础数据。
在第三个示例中,您尝试直接更改coord
,因此只是更新别名以指向其他列表,而不是使用别名来访问基础数组并更改它。因此,for List in [listA,listB]:
List = [7,8,9]
print(listA) # prints [1,2,3]; underlying data not changed
print(List) # prints [7,8,9]; List now points to the new array
现在只指向不同的列表。考虑第二个示例的修改版本:
<form id="Form1" method="post" encType="multipart/form-data" runat="server">
答案 5 :(得分:0)
要修改列表的元素,您需要提供索引然后进行修改。换句话说,这不会修改列表中的任何内容:
arr=[1,2,3]
for x in range(len(arr)): #len(arr) evaluates to 3 and range(3) makes an array of numbers from 0 up to but not including 3
arr[x]=arr[x]+1
print[arr] #Now prints [2,3,4]
所以即使你增加了值,但你没有替换列表中的值
您需要做的是,使用索引来更改值
for item in list:
#do something
答案 6 :(得分:0)
每次使用表单循环时:
item[2] = 5
该项在循环时成为对列表中每个元素的引用。使用修饰符,例如:
item = some_other_thing
将起作用,因为您正在直接修改引用。
但是,当您尝试将引用设置为等于另一个变量时:
{{1}}
你实际上并没有修改项目,你正在修改对项目的引用,并且因此从未更改过原始项目,只是丢失了对它的引用。