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

Python 将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有保留原始变量引用的解决方法?,python,Python,将可变变量传递给第二个变量并不总是按预期工作。为什么?是否有保留原始变量引用的解决方法 例如: >>> 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 = [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]

您在评论中的假设:

仍然只引用其中一个可变的部分

这是错误的

在列表上使用切片时,创建的是浅层副本,而不是视图。因此,这是两个独立的列表,它们的操作方式不同。因此,ref的更改不会反映在listA上,反之亦然

请注意,列表中的元素仍然相同。因此,内存将如下所示:

         +-------------------+         +-------+
listA -> |       list        |  ref -> |  list |
         +---+---+---+---+---+         +---+---+
         | o | o | o | o | o |         | o | o |
         +-|-+-|-+-|-+-|-+-|-+         +-|-+-|-+
           v   |   |   v   v             |   |
           20  |   |   13  14            |   |
               |   v                     |   |
               v   12 <------------------|---/
               11 <----------------------/
您应该始终查阅文档,例如numpy阵列:

通过基本切片生成的所有阵列始终是原始阵列的视图

创建列表视图 通过定义如下类,可以在列表上构建视图:

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
然后,您可以构建如下视图:

>>> listA = [10,11,12,13,14]
>>> ref = listview(listA,1,2)
>>> ref[0] = 5
>>> listA
[10, 5, 12, 13, 14]

您在评论中的假设:

仍然只引用其中一个可变的部分

这是错误的

在列表上使用切片时,创建的是浅层副本,而不是视图。因此,这是两个独立的列表,它们的操作方式不同。因此,ref的更改不会反映在listA上,反之亦然

请注意,列表中的元素仍然相同。因此,内存将如下所示:

         +-------------------+         +-------+
listA -> |       list        |  ref -> |  list |
         +---+---+---+---+---+         +---+---+
         | o | o | o | o | o |         | o | o |
         +-|-+-|-+-|-+-|-+-|-+         +-|-+-|-+
           v   |   |   v   v             |   |
           20  |   |   13  14            |   |
               |   v                     |   |
               v   12 <------------------|---/
               11 <----------------------/
您应该始终查阅文档,例如numpy阵列:

通过基本切片生成的所有阵列始终是原始阵列的视图

创建列表视图 通过定义如下类,可以在列表上构建视图:

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
然后,您可以构建如下视图:

>>> listA = [10,11,12,13,14]
>>> ref = listview(listA,1,2)
>>> ref[0] = 5
>>> listA
[10, 5, 12, 13, 14]

您不使用listA[1:3]创建视图,而是创建该部分的副本。谢谢。有没有办法从一个切片创建一个视图,并将该视图指定给一个变量名?例如,模仿numpy的行为。看,afaik没有内置视图。您不使用listA[1:3]创建视图,而是创建该部分的副本。谢谢。有没有办法从一个切片创建一个视图,并将该视图指定给一个变量名?模仿numpy的行为。看,这里没有内置视图。