Python中两种列表理解方式之间的区别?

时间:2019-03-24 01:48:25

标签: python algorithm

我正在使用动态编程来实现Matrix_Chain问题,即找出通过括号进行矩阵乘法的最小乘法数。在更改列表m的初始化方式之前,我的代码无法正常工作。有人可以解释为什么即使m = [[0]*n]*nm = [[0 for x in range(n)] for x in range(n)]组成看似相同的列表时,m = [[0]*n]*n也会导致矩阵条目无法正确更新为最低成本吗?

我制作了列表m = [[0]*5]*5并打印

for a in m:
  print(a)

我制作了清单n = [[0 for x in range(5)] for x in range(5)],并以相同的方式打印。结果是相同的。

import sys
def Matrix_Chain (p, n):

  m = [[0]*n]*n #problematic step

  for i in range (1,n):
    m[i][i] =0

  for L in range(2, n):
     for i in range(1,n-L+1):    
        j = i + L -1
        m[i][j] = sys.maxsize

        for k in range (i, j):
        q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
        if q <  m[i][j]:
          m[i][j] = q
   return m[1][n-1]

对于参数p = [1,2,3,4]n = 4,我希望看到18,即最小乘法数。但是,m = [[0]*n]*n方法将返回9223372036854775807,即sys.maxsizem = [[0 for x in range(n)] for x in range(n)]方法返回正确的答案18

1 个答案:

答案 0 :(得分:3)

这是因为

 m = [[0]*n]*n 

在m中引用同一对象。所以m [0]是m [1]是...是m [n-1]。通过示例可以更好地理解这一点。假设您有:

m = [[0] * 3] * 3

print(a)
m[0][0] = 2
print(a)

输出为:

[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[2, 0, 0], [2, 0, 0], [2, 0, 0]]

如您所见,更改m [0]中的元素会更改m [1]和m [2]中的相同位置。这是因为m [1]和m [2]只是对m [0]的引用。

对于

m = [[0 for x in range(n)] for x in range(n)]

您实际上为m中的每个位置创建了一个新列表。更改m [0]不会影响m [i](对于0