Cell assignment of a 2-dimensional Matrix in Pytho

2020-07-11 06:44发布

问题:

Below is my script, which basically creates a zero matrix of 12x8 filled with 0. Then I want to fill it in, one by one. So lets say column 2 row 0 needs to be 5. How do I do that? The example below shows how I did it and the wrong (for my needs) output:

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]

回答1:

Each row points to the same sublist. This is the result of appending the same sublist repeatedly. So when you modify one row, you end up modifying the others.

I would do this:

ncols = 12
nrows = 8
matrix = [[0] * ncols for i in range(nrows)]
matrix[2][0] = 5 

matrix contains:

[[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]]

An aside about coding style: It is poor form in Python to include the type of the object in its name. I have chosen to rename int_NumbOfColumns as ncols. If you need something more descriptive use something like column_count. Generally, mixedCase names are to be avoided, while CamelCase is generally used for class names. See PEP 8 -- Style Guide for Python Code for more.

Edit: Since you mentioned that you are new to Python, here's a little more explanation.

This is a list comprehension:

matrix = [[0] * ncols for i in range(nrows)]

It can also be written as a regular for-loop:

matrix = []
for i in range(nrows):
    matrix.append([0] * ncols)


回答2:

Each entry in list_AlignMatrix is a reference to the same object. You'll need to create a new list instance for each row in your matrix. Here's an illustration of what's happening:

>>> l = [0]
>>> l2 = [l,l,l]
>>> l2
[[0], [0], [0]]
>>> l2[0][0] = 1
>>> l2
[[1], [1], [1]]

You can use the id() function to confirm that each entry in l2 is a reference to the same object:

>>> [id(x) for x in l2]
[161738316, 161738316, 161738316]

To make new copies of your row list, you can rewrite your second loop like this:

for i in range (0, int_NumbOfRows):
    list_AlignMatrix.append(list(list_AlignMatrixRow)) 

The list constructor will create copies of list_AlignMatrixRow, as illustrated by the following example:

>>> l = range(10)
>>> l2 = list(l)
>>> l == l2
True
>>> l is l2
False


回答3:

When you append list_AlignMatrixRow, it's just appending a reference to the original list, so there's really a single 1-D list, and every row of your matrix is pointing to it. To create a new list, you need to actually create a new list:

list_AlignMatrix.append(list(list_AlignMatrixRow))

Note the call to list, which creates a list by iterating over and copying the elements of list_AlignMatrixRow



回答4:

to generate such a matrix, in python, you should use list comprihention like this if you want to produce a row with all 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 then you can create list of list in same way

list_Matrix=[[0 for j in range(12)] for i in range(8)]

now you can edit any elements

>>> 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]]

if you want to create matrix containing all column 5, u can use short circuit evaluation on list comprehension

>>> 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