gpt4 book ai didi

python - 将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有解决方法来保留原始变量引用?

转载 作者:太空宇宙 更新时间:2023-11-04 10:02:08 25 4
gpt4 key购买 nike

将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有解决方法来保留原始变量引用?

例子:

>>> 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com