当我为数组赋值时,变量的范围保持为局部(参见loc()
)。
但是,如果我访问数组的元素,则范围变为全局(请参阅glob()
)
import numpy as np
M = np.array([1])
def loc():
M = 2
return 0
def glob():
M[0] = 3
return 0
loc()
print M
>>> [1]
glob()
print M
>>> [3]
为什么会这样?如何在不修改数组全局的情况下在本地修改数组元素?我需要在我的函数中有一个循环,一次更改一个元素。
答案 0 :(得分:0)
简单解释。:
检查:
import numpy as np
M = np.array([1])
def loc():
global M
M = 2
return 0
def glob():
M[0] = 3
return 0
loc()
print M
>>>2
答案 1 :(得分:0)
你在这里混合了几件事。
首先,M = 2
创建一个名为M
的本地变量(您可以在locals()
中看到它)并阻止您访问原始M
1}}后来(虽然你没有这样做......但只是为了说明一点)。这有时被称为"shadowing"。
其次,np.array
是可变对象(与immutable object相反),对它的更改将反映在对它的任何引用中。您glob
函数中的内容是对M
的引用。
您可以将np.array
视为具有多个名称的内存,如果您更改了它,无论您使用什么名称来进行更改,这些更改都会很明显。 M[0]
只是对此内存的特定部分的引用。这反映了对象的“状态”。
如果您执行以下操作:
M = np.array([1])
def example()
another_name_for_M = M
M = 2
another_name_for_M[0] = 2
您仍会看到全局M
更改,但您正在使用新名称来访问它。
如果你使用string
,tuple
,frozenset
和所有不可变对象之类的不可变对象改变了,你将无法真正改变他们的状态。
现在问题,如果你不希望函数改变数组,只需使用copy发送np.copy
,而不是实际的:{/ p>
import numpy as np
my_array = np.array([1])
def array_mutating_function(some_array):
some_array[0] = 1337
print some_array # prints [1337]
# send copy to prevent mutating the original array
array_mutating_function(np.copy(my_array))
print my_array # prints [1]
这将有效地使它在外部作用域上不可变,因为除非在外部作用域上使用它的名称,否则该函数将不会引用它,这可能不是一个好主意。
如果该函数永远不会更改任何数组,无论发送什么数组,都要在函数内移动副本,防止它更改发送给它的任何数组:
def array_mutating_function(some_array):
some_array = np.copy(some_array)
some_array[0] = 1337