python 函数调用后变量发生意外变化

unexpected change in variable after python function call

考虑以下 python 小片段,其中我将“2”添加到 3 x 3 矩阵的第一列:

import numpy as np

def changeValue(kernel):
    kernel[0,0]=kernel[0,0]+ 2 
    kernel[1,0]=kernel[1,0]+ 2 
    kernel[2,0]=kernel[2,0]+ 2 
    return kernel

myKernel = np.array((
 [0, -1, 0],
 [-1, 5, -1],
 [0, -1, 0]), dtype="int")
CVkernel=myKernel

print(CVkernel)
a=changeValue(myKernel)
print(a)
print(CVkernel)

我得到以下输出

[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]

[[ 2 -1  0]
 [ 1  5 -1]
 [ 2 -1  0]]

[[ 2 -1  0]
 [ 1  5 -1]
 [ 2 -1  0]]

myKernel 的值破坏了 CVkernel。我认为正在进行无意的按引用调用(按引用传递?),但我不确定为什么。

如果我对函数的定义略有不同

def changeValue2(kernel):
    kernel=kernel + 2 
    return kernel

然后CVkernel保持不变

[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]

[[2 1 2]
 [1 7 1]
 [2 1 2]]

[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]

这是怎么回事? 我试着用 print(id(kernel)) 和 print(id(CVkernel)) 打印出变量的地址寄存器,结果确实如此不发光。

编辑 即使当我使用 'safe' 函数调用时, kernel=kernel + 2 , myKernel 和 CVkernel 的 id 也是相同的。

id of myKernel  139994865303344
myKernel 
[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]
id of CVKernel  139994865303344
CVKernel 
[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]

**call made to changeValue2**

id of myKernel  139994865303344
myKernel 
[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]
id of CVKernel  139994865303344
CVKernel 
[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]
output a 
[[2 1 2]
 [1 7 1]
 [2 1 2]]

如果是不同的实例,每个变量的id不应该不同吗?

我建议:

    CVkernel=myKernel.copy()

尝试如下:

def changeValue2(kernel):
    kernel += 2 
    return kernel

显示结果如下:

[[ 0 -1  0]
 [-1  5 -1]
 [ 0 -1  0]]
[[2 1 2]
 [1 7 1]
 [2 1 2]]
[[2 1 2]
 [1 7 1]
 [2 1 2]]

你很清楚它是a call by reference,但是,在kernel = kernel + 2的情况下,左边的kernel变成了另一个实例。简单地说,它与 newKernel = kernel + 2.

相同

所以,我把它改成了kernel += 2,它修改了原来的kernel实例。

Reason

永远不要直接修改对象内核 你传递给函数 changeValue2.

请检查这个link How arguments passed in python 找出当您尝试修改参数时真正发生的事情

Solution:

  1. 只需使用changeValue

  2. 使用 return 值:myKernel = changeValue2(myKernel)

  3. 只是一份yaho cho的解决方案,再次感谢:)

def changeValue2(kernel):
    kernel += 2 
    return kernel