2015-07-12 104 views
1

我对Python和Numpy相当陌生,当我将一个MATLAB程序翻译成Python时遇到了这个问题。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]] 

回答

0

当你有B[1,1] = B[1,1]/2要修改的元件一个可变数据结构 - 它改变了数据结构。在B = B/2中,您将在本地范围内重新分配B以指向其他内容。当您退出本地作用域时,此更改不会持续。

+0

这对我没有意义。该函数返回它,所以它必须是一些东西。我认为关键是'B/2'是一个新的对象。作为输入给出的对象不会改变。 – Pynchia

+0

@Pynchia也许我没说得好。我的意思是,将B分配给指向函数主体中不同对象的事实不会导致传递的参数(问题中的A)也指向不同的对象。当本地作用域消失时,对本地作用域所做的任何更改都会消失。 –

2

在第一种情况下

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指向的对象实例不受影响,即使可变。

1

与MATLAB相比,Python是一种pass by reference语言。通常一个函数被赋予对每个参数的引用。如果该功能然后修改一个参数,例如B[1,1]=...,这个变化反映在参数中。

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

根据这个答案,MATLAB中的B(1,1) = B(1,1)/2会强制一个副本,这样B不再与A共享参考。在Python中,这样的动作修改调用参数,而不进行复制。它发生在一个函数内并不重要。