乘法操作符应用到列表(数据结构)乘法操作符应用到列表(数据结构)(Multiply operator

2019-05-12 09:34发布

我读如何看待一个计算机科学家,这是“Python编程”的介绍文字。

我要说明的乘法运算符(的行为*当应用到列表)。

考虑函数make_matrix

def make_matrix(rows, columns):
"""
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
return [[0] * columns] * rows

实际产量

[[0, 7], [0, 7], [0, 7], [0, 7]]

make_matrix的正确版本是:

def make_matrix(rows, columns):
"""
  >>> make_matrix(3, 5)
  [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
matrix = []
for row in range(rows):
    matrix += [[0] * columns]
return matrix

为什么make_matrix的第一个版本出现故障(如在9.8书中解释)的原因是,

......每行是其他行的名称...

我想知道为什么

[[0] * columns] * rows

使...每行是其他行的名称...

但不是

[[0] * columns]

即为什么每个[0]连续不是其他行元件的别名。

Answer 1:

Python里一切皆是对象,和Python从不拷贝,除非明确地要求这样做。

当你做

innerList = [0] * 10

创建具有10个元素的列表, 所有的人都指的同一int对象0

由于整数对象是不可改变的 ,当你做

innerList[1] = 15

所以,它指的是另一个整数你正在改变列表的第二个元素15 。 永远奏效,因为int对象不变性。

这就是为什么

outerList = innerList * 5

将创建一个list具有5种元素的对象,每一个都是以相同的参考innerList如上刚刚。 但是,由于list对象是可变

outerList[2].append('something')

是相同的:

innerList.append('something')

因为他们是两个引用同一个list对象 。 因此,该元素在单一的最终list 。 这似乎是重复的,但事实是,世界上只有一个list对象,并把它的许多参考。

相反,如果你做

outerList[1] = outerList[1] + ['something']

在这里,你创建另一个 list对象 (使用+使用列表中明确的副本),并指派一提到它进入第二位置outerList 。 如果这种方式(不是真的追加,但创建另一个列表)“追加”的元素, innerList将不会受到影响。



Answer 2:

名单是不是基本类型,它们是通过引用传递。 列表的副本是一个指针到一个列表(在C行话)。 除非你做一个浅拷贝,你做的名单有什么事情发生到列表中的所有副本,其内容的副本。

[[0] * columns] * rows

哎呀,我们刚刚作出指针的大名单[0]。 改变之一,你改变他们。

整数不按引用传递,他们是真正的复制,因此[0] *内容实拍许多新的0和其附加到列表中。



文章来源: Multiply operator applied to list(data structure)