0

我正在阅读“如何像计算机科学家一样思考:使用 Python 第 2 版文档学习”。在第 9 章的最后有这个练习 11,它要求你编写 Python 代码以使 doctest 通过。

我最初的解决方案:

def add_column(matrix):
"""
  >>> m = [[0, 0], [0, 0]]
  >>> add_column(m)
  [[0, 0, 0], [0, 0, 0]]
  >>> n = [[3, 2], [5, 1], [4, 7]]
  >>> add_column(n)
  [[3, 2, 0], [5, 1, 0], [4, 7, 0]]
  >>> n
  [[3, 2], [5, 1], [4, 7]]
"""
result = matrix[:]
for index in range(len(matrix)):
    result[index] += [0]
return result


if __name__ == "__main__":
    import doctest
    doctest.testmod()

然而,这段代码没有通过第二次测试。我将for循环的主体更改为以下内容:

result[index] = result[index] + [0]

并且代码现在通过了所有测试。但我不明白代码中的这种变化是如何解决问题的。我认为result[index] = result[index] + [0]是 的显式形式result[0] += [0],那么为什么行为不同?

将我的答案与解决方案中提供的代码进行了比较后,我怀疑问题可能在于我如何克隆列表。在解决方案中,它是这样完成的:result = [d[:] for d in matrix],在这种情况下,我的初始for循环将起作用。但为什么result = matrix[:]不工作?它是在创建别名,而不是新对象吗?

另外,有人可以解释如何[d[:] for d in matrix]解析以及何时使用这种语法吗?我以前没有见过这种使用for循环的方式,也没有在课程中解释/演示过。

4

1 回答 1

0

由于以下原因,未克隆该列表:

result = matrix[:]

确实复制了列表;但是您还没有复制列表。Python 通过引用处理列表项,因此result[0]matrix[0]仍将指向同一个列表对象,即使认为resultmatrix是不同的列表。

[d[:] for d in matrix]克隆主列表和列表元素,因为它迭代matrix并在新列表中创建每个元素的副本(而不是使用对该元素的引用)。

您还可以使用该copy模块,该模块特别有用,因为它也处理字典,并且copy.deepcopy您可以克隆未知深度的多维列表:http: //docspy2zh.readthedocs.org/en/latest/library/copy。 html(但如果这超出了您在此处尝试学习的范围,则足够公平)。

至于'+='和'= ... + ...'之间的区别,我承认我也有点惊讶。在这种情况下,我倾向于使用result[index].append(0),这样可以避免这种歧义;但这当然不是答案。

于 2012-08-12T11:26:50.857 回答