0

list1 = [set(), set(), set()]

list2 = [set() for _ in range(3)]

print(list1 == list2) results in true

However, they seem to differ.

I was solving this problem: https://leetcode.com/problems/valid-sudoku/

Using the following does not work:

rows = [set()] * 9

cols = [set()] * 9

boxes = [set()] * 9

But replacing that with:

rows = [set() for _ in range(9)]

cols = [set() for _ in range(9)]

boxes = [set() for _ in range(9)]

makes the code work. I'm very confused as to what the difference is and how there could even be a difference if they are equal.

myers
  • 15
  • 3

2 Answers2

0

The first step is that mini_row = [set()] * 3 doesn't do the same as mini_row = [set(), set(), set()], it does the same as:

v = set()
mini_row = [v, v, v]

The difference is that in this case, the list contains the same set object three times, rather than three different sets. You can verify this by doing:

for item in mini_row:
    print(id(item))

... with both approaches.

This matters because sets are mutable, so if you do mini_row[0].add(3) it will be added to the single set that is accessible by mini_row[0], mini_row[1], or mini_row[2].

List comprehensions work differently, because they are semantically equivalent to for-loops that build lists, so the part before the for gets run 9 times instead of just once.

Jasmijn
  • 9,370
  • 2
  • 29
  • 43
0

When you use [set()]*9 you create a list with 9 references to the same set object, when you use [set() for _ in range(9)] you create a list with 9 unique set objects. For example, if you run the following:

r1 = [set()]*3
r2 = [set() for _ in range(3)]

print(r1 == r2)

r1[0].add(1)
r2[0].add(1)

print(r1)
print(r2)
print(r1 == r2)

it will print

True
[{1}, {1}, {1}]
[{1}, set(), set()]
False

You can see that modifying r1[0] modified all three entries in the list since they all refer to the same set object, but modifying r2[0] only modified one of the list entries since they are all unique set objects.

The first equality check is True (like you saw in your test) because the lists are both filled with empty sets, regardless of whether any of them refer to the same object or not. The second check is false because the sets no longer have the same contents between the two lists.

Tyler V
  • 9,694
  • 3
  • 26
  • 52