在函数内部访问数组元素时的全局作用域
Global Scope when accessing array element inside function
当我将一个值赋给一个数组时,变量的范围仍然是局部的(参见 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]
为什么会这样?如何在不全局修改数组的情况下局部修改数组的元素?我需要在我的函数中有一个循环,一次更改一个元素。
简单解释一下:
- 无法更新函数内部的全局变量,除非将其作为全局内部函数访问。
- 但是可以修改
检查:
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
你在这里混合了几样东西。
首先,M = 2
创建了一个名为M
的局部变量(你可以在locals()
中看到它)并阻止你稍后访问原始 M
(虽然你没有这样做......但只是为了说明一点)。这有时被称为 "shadowing".
其次,np.array
is a mutable object (the opposite of an immutable object),对它的更改将反映在对它的任何引用中。 glob
函数中的内容是对 M
.
的引用
您可以将 np.array
视为具有许多名称的一段内存,如果您更改了它,无论您使用什么名称访问它,更改都会很明显。 M[0]
只是对该内存特定部分的引用。这反映了对象的 "state".
如果你这样做:
M = np.array([1])
def example()
another_name_for_M = M
M = 2
another_name_for_M[0] = 2
您仍会看到全局 M
发生变化,但您正在使用新名称访问它。
如果你使用 string
、tuple
、frozenset
等,它们都是 不可变对象不能(轻易)改变,你将无法真正改变他们的状态。
现在回答你的问题,如果你不希望函数改变数组,只需发送一个 copy of it using np.copy
,而不是实际的:
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
当我将一个值赋给一个数组时,变量的范围仍然是局部的(参见 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]
为什么会这样?如何在不全局修改数组的情况下局部修改数组的元素?我需要在我的函数中有一个循环,一次更改一个元素。
简单解释一下:
- 无法更新函数内部的全局变量,除非将其作为全局内部函数访问。
- 但是可以修改
检查:
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
你在这里混合了几样东西。
首先,M = 2
创建了一个名为M
的局部变量(你可以在locals()
中看到它)并阻止你稍后访问原始 M
(虽然你没有这样做......但只是为了说明一点)。这有时被称为 "shadowing".
其次,np.array
is a mutable object (the opposite of an immutable object),对它的更改将反映在对它的任何引用中。 glob
函数中的内容是对 M
.
您可以将 np.array
视为具有许多名称的一段内存,如果您更改了它,无论您使用什么名称访问它,更改都会很明显。 M[0]
只是对该内存特定部分的引用。这反映了对象的 "state".
如果你这样做:
M = np.array([1])
def example()
another_name_for_M = M
M = 2
another_name_for_M[0] = 2
您仍会看到全局 M
发生变化,但您正在使用新名称访问它。
如果你使用 string
、tuple
、frozenset
等,它们都是 不可变对象不能(轻易)改变,你将无法真正改变他们的状态。
现在回答你的问题,如果你不希望函数改变数组,只需发送一个 copy of it using np.copy
,而不是实际的:
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