2

so I have a boolean list of lists and I changed a certain index from True to False, and it affects some others element in list of lists too. Why is it happening? is there any alternative?

test = [[True]*9]*9
test[0][1] = False
print(test)

The output:

[[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True], 
[True, False, True, True, True, True, True, True, True]]
jted95
  • 1,084
  • 1
  • 9
  • 23

3 Answers3

2

What you want to do is :

test = [[True for i in range(cols)] for j in range(rows)]
#OR
test = [[True]*cols for j in range(rows)]

The problem with doing

test = [[True]*9]*9

is that you are creating a multi-dimensional list that is referencing the same memory address that holds the True value.

It is something like having :

test = [ [True, True, True, True, True, True, True, True, True] repeated 9 times ]

where the rows all point to the same memory location of their respective columns. So when you change value in one column, it changes for the whole set of column value.

So, with the desired way,

test = [[True for i in range(9)] for j in range(9)]
test[0][1] = False
print(test)

will print :

[[True, False, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True], 
[True, True, True, True, True, True, True, True, True]]
Kaushik NP
  • 6,733
  • 9
  • 31
  • 60
0

This is caused by the fact that the star (*) operator doesn't create n new independent lists. It creates n references to the same list. Creating a list with all independent lists can be done using a list comprehension, as is already suggested:

test = [[True for i in range(cols)] for j in range(rows)]
Hielke Walinga
  • 2,677
  • 1
  • 17
  • 30
0

Yes, that's a classic python gotcha. In the inner multiplication, you make 9 copies of True. That generates a list of 9 instances of the same True object. However, the True object is immutable, so you can't change it, you just replace one of them, without affecting others.

On the contrary, in the outer multiplication, you create 9 copies of the same inner list. However, lists are mutable, so, when you change one of them, it really changes. Since the outer list consists of copies of the same list, the will all change.

You can only avoid it by creating 9 different lists

test = [[Test]*9 for i in range(9)]
blue_note
  • 27,712
  • 9
  • 72
  • 90