Python 访问函数中的数组元素时的全局范围

Python 访问函数中的数组元素时的全局范围,python,arrays,scope,Python,Arrays,Scope,当我将一个值赋给数组时,变量的作用域仍然是局部的(请参见loc())。 但是,如果访问数组的元素,作用域将变为全局(请参见glob()) 为什么会发生这种情况?如何在不全局修改数组的情况下局部修改数组的元素?我需要在函数中有一个循环,每次更改一个元素。简单解释一下: 无法更新函数内的全局变量,除非将其作为函数内的全局变量访问 但它可以修改 检查: import numpy as np M = np.array([1]) def loc(): global M M = 2

当我将一个值赋给数组时,变量的作用域仍然是局部的(请参见
loc()
)。 但是,如果访问数组的元素,作用域将变为全局(请参见
glob()

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

简单解释一下:

  • 无法更新函数内的全局变量,除非将其作为函数内的全局变量访问
  • 但它可以修改
  • 检查:

    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
    (虽然您没有这样做…但只是为了说明一点)。这有时被称为

    其次,是一个可变的对象(与对象相反),对它的更改将反映在对它的任何引用中。
    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
    正在更改,但您正在使用一个新名称来访问它

    如果您使用
    字符串
    元组
    冻结集
    等,这些都是无法(轻松)更改的不可变对象,您将无法实际更改它们的状态

    现在回答您的问题,如果您不想让函数改变数组,只需使用发送一个数组,而不是实际的数组:

    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()
    的行为和“global”的添加是明确的。这个问题与
    glob()
    的行为有关。例如,如果我在def中有一个循环,该怎么办:
    对于范围内的I(100):M[I]=I
    你可以像这样
    对于范围内的I(len(M)):M[I]=I
    得到
    M=[0,1,2…]
    len(N)
    全局declaredIt实际上没有什么区别,因为这样你可以全局地改变M。我想你必须做一些事情,比如
    M1=M.copy();对于范围内的i(len(M)):M1[i]=i
    谢谢!这一点现在清楚多了。因此,一个好的经验法则是在任何函数内处理数组的副本,例如
    M1=M.copy()…
    def array_mutating_function(some_array):
        some_array = np.copy(some_array)
        some_array[0] = 1337