使用=分配变量并不像往常一样工作

时间:2015-01-26 20:55:54

标签: python

我试图创建一个类,我用变量选择实例化,可以单独输入x,y,z,也可以输入一个数组r,我将它存储在一个numpy数组中。我试图获得的行为是当你有

a = [1,2,3]
b = a
a[0] = 4
print(a[0], b[0])

并按预期得到4,4的输出。但我有以下代码

import numpy as np

class FourVector():
    def __init__(self, ct = 0, x = 0, y = 0, z = 0, r = np.array([])):
        self.ct = ct
        self.r = r
        self.x = self.r[0]
        self.y = self.r[1]
        self.z = self.r[2]

a = FourVector(r=[1,2,3])
a.r[0] = 5
print(a.r[0], a.x)

它输出5,1。我无法弄清楚原因。搜索周围,我能找到最接近的答案是由于可变/不可变对象之间的差异。如果是这样的话,我不明白它在这里玩的地方。

3 个答案:

答案 0 :(得分:1)

我认为接近黑暗Fi指针图的答案有点帮助,但也有误导性和不完整性。当您处理像列表这样的容器时,您将涉及两个级别的指针,一个从变量到列表,另一个从列表到其内容。了解为什么您的两个示例不能以相同的方式工作

非常重要

让我们列出一个简单的场景,将两个例子合并为一个:

a = [1]
b = a
x = a[0]

这里有什么指向这种情况:

a
 \
  <list object> ---> 1
 /                  /
b                  /
                  /
x ----------------

有两个对象,整数1和列表。变量ab都指向列表,而x直接指向整数。

现在,让我们看看当您通过a[0] = 5更改此初始状况时会发生什么:

a
 \
  <list object> ---> 5
 /              
b               

x ---> 1

变量都保留在它们之前指向的相同对象上,但是列表已被修改为使其第一个元素指向与以前不同的整数。这就是为什么如果您打印ab,您会得到相同的结果,但如果您打印a[0]x会得到不同的结果。

答案 1 :(得分:0)

因为a.x未指向a.r[0]。这绝对是因为a.r[0]是不可变的。

区别在于:

a = [1,2,3]
b = a            # a is mutable, so b now points to a
a[0] = 4         # change a, so you change b
print(a[0], b[0])

对战:

a = [1,2,3]
b = a[0]         # a[0] is immutable, so copy it and point b at it
a[0] = 4         # change a, which DOESN'T CHANGE b
print(a[0], b[0])

如果这是你真正需要的东西,试试这个:

class FourVector():
    def __init__(self, ct = 0, x = 0, y = 0, z = 0, r = np.array([])):
        self.ct = ct
        self.r = r

    @property
    def x(self):
        return self.r[0]
    @property
    def y(self):
        return self.r[1]
    @property
    def z(self):
        return self.r[2]

属性是类似于属性的方法,因此您可以调用a.x,它将运行FourVector.x方法并返回结果。请注意,如果没有更多代码,则无法执行a.x = some_value

    @x.setter
    def x(self, val):
        self.r[0] = val
    # etc

答案 2 :(得分:0)

请记住,python总是通过引用进行复制,int个对象是引用。所以当你写:

 self.x = self.r[0]

您将int中的self.r[0]引用复制到self.x。但是当你写道:

a.r[0] = 5

您在对象的r[0]中放置了新引用,因此a.r[0]a.x不再是同一个对象。这是一个指针图:

转让前:

  

a.x ---&gt;无
  a.r [0] ---&gt;无

分配a.r

  

a.x ---&gt;无
  a.r [0] ---&gt; INT(1)

复制到a.x

  

a.x ---&gt; INT(1)
  a.r [0] ---&gt; INT(1)

请注意,这两个变量引用同一个对象,但它们之间没有链接。因此,在第二次分配后:

  

a.x ---&gt; INT(1)
  a.r [0] ---&gt; INT(5)