Python中的二维矩阵的单元格分配,没有numpy

时间:2012-10-21 03:12:42

标签: python matrix variable-assignment

下面是我的脚本,它基本上创建了一个填充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]

4 个答案:

答案 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的新手,那么这里有更多的解释。

这是list comprehension

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