python 二维数组(列表)赋值问题

210 阅读2分钟

背景信息

今天在写代码调试程序的时候总是出现数组的值和预期不一样的问题,最开始我是想用实现一个算法的python版本,本来源程序是C++版本的,C++版本的语句为:

int dp[N][M];
for(int i = 0; i < N; i++){
        dp[i][0] = g[i][0];
    }

对于这段C++语句而言,这是一个非常常规的语句,但是在我要实现python版本的时候,我发现其实会出现与期望值不一样的问题。下面是原始有bug的python代码:

dp = [[0]*M] * N
for i in range(N):
    dp[i][0] = g[i][0]

原理分析

在这段程序中,我会发现一个问题,在给二维数组进行赋值的时候,会出现整列都会赋值的情况,如:

In [1]: arr = [[0]*5]*5
In [2]: arr
Out[2]: 
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]
 
In [3]: arr[0][0] = 1
In [4]: arr
Out[4]: 
[[1, 0, 0, 0, 0],
 [1, 0, 0, 0, 0],
 [1, 0, 0, 0, 0],
 [1, 0, 0, 0, 0],
 [1, 0, 0, 0, 0]]

这是因为[[0]*5]*5表示的是指向[0]*5这个列表的引用,所以说当你修改其中某一个值的时候,整个列表的值都会被改变。问题出现在我们的初始化方法上,只要我们改进我们的初始化方式,不采取引用的方式就可以解决这个问题。例如:

In [1]: arr = [[0]*5 for _ in range(5)]
In [2]: arr
Out[2]: 
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]

In [3]: arr[0][0] = 1
In [4]: arr
Out[4]: 
[[1, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]
 

问题解决

所以说对于我们原来的程序,我们就可以这样进行初始化为一个N行M列的元素全是0的二维数组:

dp = [[ 0 for _ in range(M)] for _ in range(N)]
for i in range(N):
    dp[i][0] = g[i][0]