Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为变量赋值为=isn';他不像往常那样工作_Python - Fatal编程技术网

Python 为变量赋值为=isn';他不像往常那样工作

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

我试图创建一个类,在这个类中,我可以选择变量进行实例化,或者单独输入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。我不明白为什么。环顾四周,我能找到的最接近答案是,这是由于可变/不可变对象之间的差异造成的。如果是这样的话,我不明白它是从哪里来的。

因为
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语言的语言,则一开始会感到困惑。