Python 为变量赋值为=isn';他不像往常那样工作
我试图创建一个类,在这个类中,我可以选择变量进行实例化,或者单独输入x、y、z,或者输入一个数组r,我将其存储在numpy数组中。我想要表现的是当你Python 为变量赋值为=isn';他不像往常那样工作,python,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.arr
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。我不明白为什么。环顾四周,我能找到的最接近答案是,这是由于可变/不可变对象之间的差异造成的。如果是这样的话,我不明白它是从哪里来的。因为
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_值
@x.setter
def x(self, val):
self.r[0] = val
# etc
记住,python总是通过引用进行复制,int
对象是引用。所以当你写作时:
self.x = self.r[0]
a.r[0] = 5
将self.r[0]
中的int
引用复制到self.x
中。但当你写作时:
self.x = self.r[0]
a.r[0] = 5
您已在对象的r[0]
中放置了一个新引用,因此a.r[0]
和a.x
不再是同一对象。下面是指针图:
派遣前:
a、 x--->无
a、 r[0]-->无
分配a.r
:
a、 x--->无
a、 r[0]-->int(1)
复制到a.x
:
a、 x--->int(1)
a、 r[0]-->int(1)
请注意,这两个变量引用同一个对象,但它们彼此之间没有链接。因此,在第二次分配之后:
a、 x--->int(1)
a、 r[0]-->int(5)
我认为用指针图接近Darkey-Fi的答案有些帮助,但也有误导性和不完整性。当您处理像列表这样的容器时,将涉及两个级别的指针,一个是从变量到列表的指针,另一个是从列表到其内容的指针。这对于理解为什么两个示例的工作方式不同很重要
让我们设计一个简单的场景,将两个示例合并为一个:
a = [1]
b = a
x = a[0]
以下是在这种情况下的要点:
a
\
<list object> ---> 1
/ /
b /
/
x ----------------
所有变量都保持指向它们之前指向的相同对象,但该列表已被修改,使其第一个元素指向与以前不同的整数。这就是为什么如果打印a
和b
会得到相同的结果,但是如果打印a[0]
和x
会得到不同的结果。因此,如果我建议不可变的对象是那些在赋值时可以复制的对象,而可变对象实际上是相互指向的吗?@user4496239这是正确的说法,是的。从技术上讲,所有对象都是通过引用复制的,但是当您执行x=r[0]
操作时,您将x
指向整数1
的引用,而不是对r
@user4496239中第一个元素的引用,它确实是这样显示的,但是,因为如果您执行了类似r=['sub','list',2,3]
,a=r[0]
,r[0][0]。插入(0,“另一”)
然后a==['other',sub',list]
。请记住,赋值改变了,例如,r[0][0]=[“另一个”,“子”,“列表”]
将离开a==[“子”,“列表”]
我认为这个答案关于可变性的评论是完全错误的。虽然易变性有时会对赋值产生影响(例如,在a+=b
之后a
是否引用同一对象),但在问题中描述的情况下,易变性并不重要。即使r[0]
像列表一样是一个可变对象,如果您重新分配它(而不是改变子值),您仍然会在r[0]
和x
中得到不同的值。也就是说,您建议使用属性来实现x
、y
和z
属性,这是一个非常好的建议。@Blckknght绝对正确。我试图在评论中澄清,但我觉得简化的“mutable=reference,immutable=copy”足以给出一个大概的答案。你走在了前面,很多人都希望它能起到相反的作用。如果你想更深入地理解,请阅读本文的第一部分。实际上,Python中的赋值非常简单,但如果您来自类似C语言的语言,则一开始会感到困惑。