问题描述
谁能解释为什么fun1
不会修改变量y
的值,而fun2
可以修改?我需要逐行修改一个数组,但是同时更新y
并不是我想要的行为.
Could anyone explain why fun1
doesn't modify the value of the variable y
, while fun2
does? I need to modify an array row by row, but updating y
at the same time is not the behavior I'm looking for.
def fun1(x):
x = 2*x
return x
def fun2(x):
for i in range(0, x.shape[0]):
x[i, :] = 2*x[i, :]
return x
y = np.random.uniform(0, 100, (10, 10))
z1 = fun1(y)
print(np.array(z1 == y).all())
# False
z2 = fun2(y)
print(np.array(z2 == y).all())
# True
推荐答案
修改您的函数以显示对象的id
Modifying your function to show the id
of the objects
def fun1(x):
print(id(x),id(y))
x = 2*x
print(id(x))
return x
In [315]: y = np.arange(3)
In [316]: id(y)
Out[316]: 140296824014768
In [317]: z = fun1(y)
140296824014768 140296824014768
140296823720096
In [318]: id(z)
Out[318]: 140296823720096
因此,由y
引用的数组将传递给函数,并且可以由x
(参数变量)和y
(外部变量)两者引用.但是赋值更改了x
引用-该对象被传递回z
. y
不变.
So the array referenced by y
is passed to the function, and can be referenced by both x
(the argument variable) and y
(the external variable). But the assignment changes the x
reference - that object is passed back to z
. y
is unchanged.
def fun2(x):
print(id(x), id(y))
x[0] = 23
print(id(x))
return x
使用第二个功能,赋值会更改x
的元素,但不会更改所引用对象的id
. y
,x
和z
都引用相同的数组.
With this 2nd function, the assignment changes an element of x
, but doesn't change the id
of the referenced object. y
,x
and z
all reference the same array.
In [320]: y
Out[320]: array([0, 1, 2])
In [321]: id(y)
Out[321]: 140296824014768
In [322]: z = fun2(y)
140296824014768 140296824014768
140296824014768
In [323]: id(z)
Out[323]: 140296824014768
In [324]: z
Out[324]: array([23, 1, 2])
In [325]: y
Out[325]: array([23, 1, 2])
如果在将y
复制到函数之前或在函数内部进行复制,则修改x
不会修改y
.
If we make a copy of y
, either before passing it to the function, or inside the function, then modifying x
will not modify y
.
In [327]: y = np.arange(3)
In [328]: id(y)
Out[328]: 140296823645328
In [329]: z = fun2(y.copy())
140296823647968 140296823645328
140296823647968
In [330]: id(z)
Out[330]: 140296823647968
In [331]: z
Out[331]: array([23, 1, 2])
In [333]: y
Out[333]: array([0, 1, 2])
我们将数组传递给函数的事实并没有改变对副本的需求.即使只是在顶层执行操作,我们也会得到相同的行为.
The fact that we are passing the array to a function doesn't change the need for a copy. We'd get the same behavior even we just performed the action at the top level.
In [334]: y = np.arange(3)
In [335]: x = y.copy()
In [336]: x[:2]=22
In [337]: x
Out[337]: array([22, 22, 2])
In [338]: y
Out[338]: array([0, 1, 2])
如果对象是列表,我们将得到相同的行为:
We get the same behavior if the object is a list:
In [339]: yl = [1,2,3]
In [340]: fun1(yl)
140296925836360 ...
140296824729096
Out[340]: [1, 2, 3, 1, 2, 3]
In [341]: fun2(yl)
140296925836360 ...
140296925836360
Out[341]: [23, 2, 3]
In [343]: yl
Out[343]: [23, 2, 3]
这篇关于python函数在调用范围内修改变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!