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