我试图创建一个类,我用变量选择实例化,可以单独输入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。我无法弄清楚原因。搜索周围,我能找到最接近的答案是由于可变/不可变对象之间的差异。如果是这样的话,我不明白它在这里玩的地方。
答案 0 :(得分:1)
我认为接近黑暗Fi指针图的答案有点帮助,但也有误导性和不完整性。当您处理像列表这样的容器时,您将涉及两个级别的指针,一个从变量到列表,另一个从列表到其内容。了解为什么您的两个示例不能以相同的方式工作
非常重要让我们列出一个简单的场景,将两个例子合并为一个:
a = [1]
b = a
x = a[0]
这里有什么指向这种情况:
a
\
<list object> ---> 1
/ /
b /
/
x ----------------
有两个对象,整数1
和列表。变量a
和b
都指向列表,而x
直接指向整数。
现在,让我们看看当您通过a[0] = 5
更改此初始状况时会发生什么:
a
\
<list object> ---> 5
/
b
x ---> 1
变量都保留在它们之前指向的相同对象上,但是列表已被修改为使其第一个元素指向与以前不同的整数。这就是为什么如果您打印a
和b
,您会得到相同的结果,但如果您打印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)