使用*操作符创建列表和在range中使用_有什么区别?



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(就像您在测试中看到的那样),因为两个列表都被空集填充,不管它们是否引用相同的对象。第二次检查为假,因为两个列表之间的集合不再具有相同的内容。

最新更新