Change element in list of a list

Hey guys.

I’m new in python and I got a problem:

I have a matrix m0 = [[0,0,0],[0,0,0]] and the following

def t(m0):
for i in m0:
for j in i:
m0[i][j] = 5
print(m0)

When I run it I get the TypeError: list indices must be integers or slices, not list.
I don’t understand why this happens.

Thank you.

Try printing the value of i as you loop:

for i in m0:
    print(i)

You will see that i will equal the list [0, 0, 0].

If you have a list-of-lists modelling a two-dimensional array, possibly
the easiest way to loop over the indices of the lists:

m0 = [[0, 0, 0], [0, 0, 0]]
for i in range(len(m0)):
    for j in range(m0[i]):
        print(m0[i][j])

Slightly more efficient will be something like this:

for i, row in enumerate(m0):
    for j, x in enumerate(row):
        print("row", i, "column", j, "element" x)

It’s unclear for me whether replaced numbers are all the same or not. Your function can be easily modified to replace all values to 5:

>>> def test(matrix):
...     for row in matrix:
...         for i, _ in enumerate(row):
...             row[i] = 5
...     print(matrix)
...
>>> test([[0,0], [0,0]])
[[5, 5], [5, 5]]

If there is no problem of creating new object then list comprehension is much more concise (with different replace options):

>>> m = [[0, 0], [0, 0]]
>>> [[5 for item in row] for row in m]
[[5, 5], [5, 5]]
>>> [[row_counter for item in row] for row_counter, row in enumerate(m, start=1)]
[[1, 1], [2, 2]]
>>> [[i for i, _ in enumerate(row, start=1)] for row in m]
[[1, 2], [1, 2]]
>>> [[row_counter * len(row) + i for i, _ in enumerate(row, start=1)] for row_counter, row in enumerate(m)]
[[1, 2], [3, 4]]
>>> from itertools import count
>>> counter = count(1)
>>> [[next(counter) for item in row] for row in m]
[[1, 2], [3, 4]]

The issue with your original code is that m0 contains two lists. When you do something like this in Python:
for i in m0:
the variable i is NOT an indexing number but an object item in the object m0. So it’s actually the first list in m0.
You cannot index a list by a list, only be a number (so mylist[i] is the ith item in mylist but i must be a number that indexes mylist. So what you need is for both your i and j to be indexing numbers. You achieve this by doing something like:
for i in <some range of numbers>:
In this case i will be an index number starting from 0 (zero base numbering).
So try this:

def t2(m0):
  for i in range(len(m0)): #len(m0)==2 because two lists inside m0 and its range == 0, 1
    insidelist = m0[i] # when i=0 this is the first list inside m0
    for j in range(len(insidelist)): # len == 3 for [0,0,0] and range == 0, 1, 2
      m0[i][j] = 5
  print(m0)

I’ll leave it as an exercise to learn about range.

Tank you very much.

You said “I don’t understand why this happens.” I answered that. If you
read my answer, and run the code I suggested you run, you should
understand why it happens.

I then gave you not one but two solutions for how to fix it. All you
needed to do was change the calls to print() to do whatever you wanted
to do instead.

You are trying to index lists with a list instead of an integer.

m = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]

m[0]  # returns [1, 2, 3]
m[[1, 2, 3]]  # raises an error.

When you iterate over m in a for-loop, the loop doesn’t give you the
indices 0, 1, 3. It gives you the elements of m, namely:

[1, 2, 3]

as the first element, then [4, 5, 6], then [7, 8, 9].

As a beginner, you will learn a million times more by actually
experimenting with code, and printing the values so you can see what
they are, then by having us just hand you a chunk of code that you copy
and paste and have no idea how or why it works.

As a beginner, your best friend in the world is print() :slight_smile:

Okay thank you for this advice.