访问函数内部的数组元素时的全局范围

时间:2015-02-17 16:47:42

标签: python arrays scope

当我为数组赋值时,变量的范围保持为局部(参见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]

为什么会这样?如何在不修改数组全局的情况下在本地修改数组元素?我需要在我的函数中有一个循环,一次更改一个元素。

2 个答案:

答案 0 :(得分:0)

简单解释。:

  1. 无法更新函数内的全局变量,除非将其作为全局内部函数访问。
  2. 但它可以修改
  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
    

答案 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更改,但您正在使用新名称来访问它。

如果你使用stringtuplefrozenset和所有不可变对象之类的不可变对象改变了,你将无法真正改变他们的状态。

现在问题,如果你不希望函数改变数组,只需使用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