【问题标题】:Python function not supposed to change a global variablePython函数不应该更改全局变量
【发布时间】:2015-07-12 21:28:26
【问题描述】:

我对 Python 和 Numpy 还很陌生,在将 MATLAB 程序翻译成 Python 时遇到了这个问题。

据我所知,下面的代码通过修改全局变量表现异常,即使它不应该这样做。

import numpy as np

A = np.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

def function(B):
    B[1,1] = B[1,1] / 2
    return B

C = function(A)

print(A)

输出是:

[[0 1 2]
 [3 2 5]
 [6 7 8]]

函数将矩阵的中间数除以二并返回。但它似乎也在改变全局变量。

在这里,这个问题可以很容易地避免,但我试图理解它为什么会出现。

由于某些原因,如果函数将整个矩阵除以 2,则不会发生这种情况。

import numpy as np

A = np.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

def function(B):
    B = B / 2
    return B

C = function(A)

print(A)

输出是:

[[0 1 2]
 [3 4 5]
 [6 7 8]]

【问题讨论】:

    标签: python function variables numpy global


    【解决方案1】:

    第一种情况

    def function(B):
        B[1,1] = B[1,1] / 2
        return B
    

    您更改了名称B 所指向的可变对象的特定元素的内容。如上一个答案中所述。

    而在

    def function(B):
        B = B / 2
        return B
    

    关键是B / 2 完全是一个新对象。作为输入给出的对象不会改变。

    您将其重新分配给本地名称B 这一事实并不重要。它使B 不再指向作为函数输入提供的原始对象,而是指向一个全新的对象实例。该函数返回。

    因此,正确地,名称A 指向的对象实例不受影响,即使是可变的。

    【讨论】:

      【解决方案2】:

      与 MATLAB 相比,Python 是一种pass by reference 语言。通常为函数提供对每个参数的引用。如果该函数随后修改了一个参数,例如B[1,1]=...,变化反映在参数中。

      http://www.mathworks.com/matlabcentral/answers/152-can-matlab-pass-by-reference 解释了 MATLAB 通过句柄 v. 按值传递参数之间的区别。实际上,Python/numpy 通过句柄传递。

      根据这个答案,MATLAB 中的B(1,1) = B(1,1)/2 将强制复制,因此B 不再与A 共享引用。在Python 中,这样的操作会修改调用参数,而不需要复制。它发生在函数中并不重要。

      【讨论】:

        【解决方案3】:

        当您拥有B[1,1] = B[1,1]/2 时,您正在修改可变数据结构的元素——这会改变数据结构。在B = B / 2 中,您在本地范围内重新分配 B 以指向其他内容。当您退出本地范围时,该更改不会持续存在。

        【讨论】:

        • 这对我来说没有意义。函数返回它,所以它一定是什么。我认为重点是B / 2 是一个新对象。作为输入给出的对象没有改变。
        • @Pynchia 也许我的措辞不好。我的意思是,将 B 分配为指向函数主体中的不同对象这一事实不会导致传递的参数(问题中的 A)也指向不同的对象。当本地范围消失时,您对本地范围所做的任何更改都会消失。
        猜你喜欢
        • 2016-11-03
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-31
        相关资源
        最近更新 更多