下面是我的脚本,它基本上创建了一个填充0的12x8的零矩阵。然后我想逐个填写它。所以说第2列第0行需要是5.我该怎么做?下面的例子显示了我是如何做到这一点以及错误的(根据我的需要)输出:
list_MatrixRow = []
list_Matrix = [] #Not to be confused by what the book calls, optimal alignment score matrix
int_NumbOfColumns = 12
int_NumbOfRows = 8
for i in range (0, int_NumbOfColumns): # Puts Zeros across the first Row
list_AlignMatrixRow.append(0)
for i in range (0, int_NumbOfRows):
list_AlignMatrix.append(list_AlignMatrixRow)
#add the list in another list to make matrix of Zeros
#-------------------THE ACTUAL PROBLEMATIC PART; ABOVE IS FINE(It Works)------------
list_AlignMatrix[2][0] = 5
# This is what logically makes sense but here is the output
# which happens but I don't want (there should be all 0s and
# only one 5 on the cell [2][0]):
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
答案 0 :(得分:9)
每行指向相同的子列表。这是重复附加相同子列表的结果。因此,当您修改一行时,最终会修改其他行。
我会这样做:
ncols = 12
nrows = 8
matrix = [[0] * ncols for i in range(nrows)]
matrix[2][0] = 5
matrix
包含:
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[5, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
关于编码风格:Python中的不良形式是在其名称中包含对象的类型。我已选择将int_NumbOfColumns
重命名为ncols
。如果您需要更具描述性的内容,请使用column_count
之类的内容。通常,要避免使用mixedCase名称,而CamelCase通常用于类名。有关详情,请参阅PEP 8 -- Style Guide for Python Code。
编辑:既然你提到你是Python的新手,那么这里有更多的解释。
matrix = [[0] * ncols for i in range(nrows)]
它也可以写成常规for循环:
matrix = []
for i in range(nrows):
matrix.append([0] * ncols)
答案 1 :(得分:5)
list_AlignMatrix
中的每个条目都是对同一个对象的引用。您需要为矩阵中的每一行创建一个新的list
实例。以下是正在发生的事情的说明:
>>> l = [0]
>>> l2 = [l,l,l]
>>> l2
[[0], [0], [0]]
>>> l2[0][0] = 1
>>> l2
[[1], [1], [1]]
您可以使用id()
函数确认l2
中的每个条目都是对同一对象的引用:
>>> [id(x) for x in l2]
[161738316, 161738316, 161738316]
要制作行列表的新副本,您可以像这样重写第二个循环:
for i in range (0, int_NumbOfRows):
list_AlignMatrix.append(list(list_AlignMatrixRow))
list
构造函数将创建list_AlignMatrixRow
的副本,如以下示例所示:
>>> l = range(10)
>>> l2 = list(l)
>>> l == l2
True
>>> l is l2
False
答案 2 :(得分:1)
当您追加list_AlignMatrixRow
时,它只是附加对原始列表的引用,因此实际上只有一个1-D列表,并且矩阵的每一行都指向它。要创建新列表,您需要实际创建一个新列表:
list_AlignMatrix.append(list(list_AlignMatrixRow))
注意对列表的调用,它通过迭代并复制list_AlignMatrixRow的元素来创建列表
答案 3 :(得分:1)
生成这样的矩阵,在python中,你应该使用list comprihention这样 如果你想生成一个全0的行,
>>> import copy
>>> list_MatrixRow=[0 for i in range(12)]
>>> list_MatrixRow
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
CE 然后你可以用同样的方式创建列表列表
list_Matrix = [[0表示范围(12)中的j],范围(8)中的i]
现在您可以编辑任何元素
>>> list_Matrix[0][2]=12345
>>> list_Matrix[0][2]
12345
>>> list_Matrix
[[0, 0, 12345, 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, 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, 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, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
如果你想创建包含所有第5列的矩阵,你可以使用列表理解的短路评估
>>> list_MatrixRow=[(i==0 and 5 or 0) for i in range(12)]
>>> list_MatrixRow
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> list_Matrix=[list_MatrixRow for i in range(8)]
>>> list_MatrixRow
[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> list_Matrix
[[5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
>>> list_Matrix[0][0]
5