我是初学者,在学习python时会感到困惑.如果我有以下python代码:
import numpy as np
X = np.array([1,0,0])
Y = X
X[0] = 2
print Y
Run Code Online (Sandbox Code Playgroud)
Y将被证明是 array([2, 0, 0])
但是,如果我执行以下操作:
import numpy as np
X = np.array([1,0,0])
Y = X
X = 2*X
print Y
Run Code Online (Sandbox Code Playgroud)
Y 还是 array([1,0,0])
到底是怎么回事?
想一想:python中的等号分配引用.
Y = X 使Y指向X指向的相同地址
X[0] = 2 使x [0]指向2
X = 2*X 使X指向一个新的东西,但Y仍然指向原始X的地址,所以Y不变
这不完全正确,但它足够接近理解原则
这是因为X并且Y是对同一个对象的引用,np.array([1,0,0])这意味着无论调用是通过 X或完成的Y,结果都是相同的,但更改一个引用,则无效.
如果你写:
X = np.array([1,0,0])
Y = X
Run Code Online (Sandbox Code Playgroud)
基本上什么情况是,有两个局部变量 X和Y那指同一个对象.所以内存看起来像:
+--------+
Y -> |np.array| <- X
+--------+
|[1,0,0] |
+--------+
Run Code Online (Sandbox Code Playgroud)
现在如果你这样做X[0] = 2基本上是短的:
X.__setitem__(0,2)
Run Code Online (Sandbox Code Playgroud)
所以你在对象上调用一个方法.所以现在内存看起来像:
+--------+
Y -> |np.array| <- X
+--------+
|[2,0,0] |
+--------+
Run Code Online (Sandbox Code Playgroud)
如果你写的话:
X = 2*X
Run Code Online (Sandbox Code Playgroud)
首先2*X是评估.现在2*X简称:
X.__rmul__(2)
Run Code Online (Sandbox Code Playgroud)
(Python的首先查找,如果2支持__mul__的X,但由于2将引发一个NotImplementedException),Python将回退到X.__rmul__).现在X.__rmul__ 不改变X:它保持X原样,但构造一个新数组并返回它.X抓住现在引用该数组的新数组.
它创建一个新array对象:array([4, 0, 0])然后X 引用该新对象.所以现在内存看起来像:
+--------+ +--------+
Y -> |np.array| X ->|np.array|
+--------+ +--------+
|[2,0,0] | |[4,0,0] |
+--------+ +--------+
Run Code Online (Sandbox Code Playgroud)
但正如您所看到的,Y仍然引用旧对象.