list1 = [set(), set(), set()]
list2 = [set() for _ in range(3)]
print(list1 == list2)
生成true
然而,它们似乎不同。
我正在解决这个问题:https://leetcode.com/problems/valid-sudoku/
使用以下命令无效:
rows = [set()] * 9
cols = [set()] * 9
boxes = [set()] * 9
但是用:
rows = [set() for _ in range(9)]
cols = [set() for _ in range(9)]
boxes = [set() for _ in range(9)]
使代码工作。我很困惑,到底有什么区别,如果它们是相等的,怎么会有区别。
第一步是mini_row = [set()] * 3
不做同样的mini_row = [set(), set(), set()]
,它做同样的:
v = set()
mini_row = [v, v, v]
的区别在于,在这种情况下,列表包含相同的set对象三次,而不是三个不同的集合。您可以这样验证:
for item in mini_row:
print(id(item))
…
这很重要,因为集合是可变的,所以如果你做了mini_row[0].add(3)
,它将被添加到mini_row[0]
,mini_row[1]
或mini_row[2]
可访问的单个集合。
列表推导的工作方式不同,因为它们在语义上等同于构建列表的for循环,所以for
之前的部分运行9次而不是一次。
当您使用[set()]*9
时,您创建了一个包含9个对相同set对象的引用的列表,当您使用[set() for _ in range(9)]
时,您创建了一个包含9个唯一set对象的列表。例如,如果执行以下命令:
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)
它将打印
True
[{1}, {1}, {1}]
[{1}, set(), set()]
False
可以看到,修改r1[0]
修改了列表中的所有三个条目,因为它们都指向同一个集合对象,但修改r2[0]
只修改了列表中的一个条目,因为它们都是唯一的集合对象。
第一个相等性检查为True(就像您在测试中看到的那样),因为两个列表都被空集填充,不管它们是否引用相同的对象。第二次检查为假,因为两个列表之间的集合不再具有相同的内容。