将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有解决方法来保留原始变量引用?
例子:
>>> listA = [10,11,12,13,14]
# this works as I would expect it:
>>> ref = listA
>>> ref[0] = 20
>>> listA
[20, 11, 12, 13, 14]
# but this doesn't
>>> ref = listA[1:3] # still making reference to a mutable (only part of it)
>>> ref
[11, 12]
>>> ref[0]=30
>>> listA
[20, 11, 12, 13, 14]
最佳答案
您在评论中的假设:
# still making reference to a mutable (only part of it)
错误。
当您在 list
上使用切片时s,您创建了一个浅拷贝,不是 View 。所以这是两个独立的列表,它们的运作方式不同。因此更改为 ref
不会反射(reflection)listA
反之亦然。
请注意,列表中的元素仍然是相同的。所以内存看起来像:
+-------------------+ +-------+
listA -> | list | ref -> | list |
+---+---+---+---+---+ +---+---+
| o | o | o | o | o | | o | o |
+-|-+-|-+-|-+-|-+-|-+ +-|-+-|-+
v | | v v | |
20 | | 13 14 | |
| v | |
v 12 <------------------|---/
11 <----------------------/
这里没关系,因为int
s 是不可变的。但是,如果您要在 listA
的元素上调用一个方法更改该对象的状态,当您通过 ref[0]
引用该元素时,更改也会反射(reflect)出来例如。
这种行为并不总是,例如 numpy
数组在切片完成时使用 View 。例如:
>>> import numpy as np
>>> a = np.arange(10)
>>> b = a[1:3] # slicing in numpy generates a "view"
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([1, 2])
>>> b[0] = 5
>>> a
array([0, 5, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b
array([5, 2])
您应该始终查阅文档,例如 here对于 numpy 数组:
(...)
All arrays generated by basic slicing are always views of the original array.
(...)
创建 listview
您可以通过定义一个类来构建 ListView ,如下所示:
class listview:
def __init__(self,data,frm=None,len=None):
self.data = data
self.frm = frm
self.len = len
def __getitem__(self,idx):
if self.frm is not None:
idx += self.frm
if self.len is not None and idx >= self.len:
raise Exception('Index out of range!')
return self.data[idx]
def __setitem__(self,idx,value):
if self.frm is not None:
idx += self.frm
if self.len is not None and idx >= self.len:
raise Exception('Index out of range!')
self.data[idx] = value
def __len__(self):
frm = 0
if self.frm is not None:
frm = self.frm
if self.len is not None:
return min(self.len,len(self.data)-frm)
return len(self.data)
def __repr__(self):
return 'listview(%s,%s,%s)'%(self.data,self.frm,self.len)
# ... and so on
然后你可以构造一个像这样的 View :
>>> listA = [10,11,12,13,14]
>>> ref = listview(listA,1,2)
>>> ref[0] = 5
>>> listA
[10, 5, 12, 13, 14]
关于python - 将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有解决方法来保留原始变量引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42975552/