Ama*_*wal 11 python python-datamodel
我正在阅读如何像计算机科学家一样思考,这是"Python编程"的入门文本.
我想澄清*应用于列表时multiply operator()的行为.
考虑函数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
Run Code Online (Sandbox Code Playgroud)
实际输出是
[[0, 7], [0, 7], [0, 7], [0, 7]]
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
第一版make_matrix失败的原因(如9.8中的书中所述)就是这样
...每行是其他行的别名......
我想知道为什么
[[0] * columns] * rows
Run Code Online (Sandbox Code Playgroud)
原因......每一行都是其他行的别名......
但不是
[[0] * columns]
Run Code Online (Sandbox Code Playgroud)
即为什么[0]连续的每一行都不是其他行元素的别名.
nos*_*klo 18
python中的所有东西都是对象,除非明确要求,否则python永远不会复制.
当你这样做
innerList = [0] * 10
Run Code Online (Sandbox Code Playgroud)
您创建一个包含10个元素的列表,所有这些int0元素都引用同一个对象.
由于整数对象是不可变的,所以当你这样做时
innerList[1] = 15
Run Code Online (Sandbox Code Playgroud)
您正在更改列表的第二个元素,以便它引用另一个整数15.这总是有效的,因为int对象不变性.
这就是为什么
outerList = innerList * 5
Run Code Online (Sandbox Code Playgroud)
将创建一个list具有5个元素的对象,每个元素都是与上面相同innerList的引用.但由于list对象是可变的:
outerList[2].append('something')
Run Code Online (Sandbox Code Playgroud)
是相同的:
innerList.append('something')
Run Code Online (Sandbox Code Playgroud)
因为它们是对同一list对象的两个引用.因此元素最终会出现在那个单元中list.它似乎是重复的,但事实是只有一个list对象,并且很多引用它.
相反,如果你这样做
outerList[1] = outerList[1] + ['something']
Run Code Online (Sandbox Code Playgroud)
在这里,您要创建另一个 list对象(使用+列表是一个显式副本),并将其引用分配到第二个位置outerList.如果你以这种方式"附加"元素(不是真正附加,而是创建另一个列表),innerList将不受影响.