List[:][:] 在 Python 中到底做了什么?
What does List[:][:] really do in Python?
我尝试使用拼接运算符复制二维数组。直觉上,如果我这样做,感觉就像:
L = [[5, 6], [7, 8]]
M = L[:][:]
那么 M
将是 L
中每个 嵌套 元素的克隆副本。所以我可以更改 M[0]
中的项目而不更改 L
:
M[1] = [3, 4]
M[0][1] = 2
但是当我这样做时:
print(L)
#returns [[5,2],[7,8]]
当我执行 [:][:]
操作时,Python 的内存中到底发生了什么?
只需复制运算符左侧的列表[:]
。
[:][:]
copy of copy
。你可以做 M = L[:][:][:][:][:][:][:][:][:][:][:][:][:][:]
并且它的工作方式相同 :D
要同时复制嵌套列表,您应该像 M = [x[:] for x in L[:]]
那样做
那么 M 将是 L 中每个嵌套元素的克隆副本。这是不正确的,因为 L[:][:]
与 (L[:])[:]
相同,它是原始列表副本的副本。
M[1] = [3, 4]
这里修改第二项COPY
.
但是这里 M[0][1] = 2
你正在修改原始嵌套数组的一个项目,因为 [:]
没有对嵌套列表进行任何复制操作并且复制的原始列表项目不是 "simple".
警告! 在 Python 中,当它是一个列表并执行 x = y
时,更改 y
中的值会更改 x
.
这里不是按值复制,而是按引用复制。例如。
>>> x = [[1,2], [3,4]]
>>> y = x
>>> y[0][1] = 5
>>> x
[[1, 5], [3, 4]]
但是您使用 x = y[:]
进行复制的方式是正确的。 [:]
的链接是多余的。
首先让我们了解如何真正 "copy by value" 这个嵌套列表。为此,一般来说,您可以使用 copy
模块。
>>> import copy
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y[0][1] = 5
>>> x
[[1, 2], [3, 4]]
>>> y
[[1, 5], [3, 4]]
从 https://docs.python.org/3/faq/programming.html#how-do-i-copy-an-object-in-python 开始,执行 y = x[:]
与使用 copy.copy
相同
现在回到 [:]
表示法。如果我们深入了解嵌套并查看类型:
>>> x = [[1,2], [3,4]]
>>> type(x)
<class 'list'>
>>> type(x[0])
<class 'list'>
>>> type(x[:])
<class 'list'>
>>> type(x[:][0])
<class 'list'>
>>> type(x[:][0][0])
<class 'int'>
>>> type(x[:][0][0][0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
我们看到,如果我们在某些时候直接评估内部列表中的值,则整数值不是列表,因此我们无法从中获取索引。
当我们继续做时会发生什么 x[:][:][:][:][:]
,我们看到它检查允许我们继续访问列表但是 我们真的进入了嵌套列表值吗我们做 [:]
?
>>> type(x[:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:][:])
<class 'list'>
这里我们看到类型没有改变,如果我们查看实际值,如果我们开始复制它:
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:][:])
>>> y
[[1, 2], [3, 4]]
本质上,您在第一个 x[:]
访问完整列表,然后 [:]
的连续链接不完全是 accessing/traversing 嵌套循环,但是 只是重新复制复制的列表。
将 z=x[:][:]
视为:
y = x[:]
z = y[:]
现在阅读有关切片的 documentations/questions 是一个很好的观点
- https://docs.python.org/3/tutorial/introduction.html
- Understanding slice notation
要深入挖掘,您必须深入实施。
https://github.com/python/cpython/blob/master/Objects/sliceobject.c
我尝试使用拼接运算符复制二维数组。直觉上,如果我这样做,感觉就像:
L = [[5, 6], [7, 8]]
M = L[:][:]
那么 M
将是 L
中每个 嵌套 元素的克隆副本。所以我可以更改 M[0]
中的项目而不更改 L
:
M[1] = [3, 4]
M[0][1] = 2
但是当我这样做时:
print(L)
#returns [[5,2],[7,8]]
当我执行 [:][:]
操作时,Python 的内存中到底发生了什么?
只需复制运算符左侧的列表[:]
。
[:][:]
copy of copy
。你可以做 M = L[:][:][:][:][:][:][:][:][:][:][:][:][:][:]
并且它的工作方式相同 :D
要同时复制嵌套列表,您应该像 M = [x[:] for x in L[:]]
那么 M 将是 L 中每个嵌套元素的克隆副本。这是不正确的,因为 L[:][:]
与 (L[:])[:]
相同,它是原始列表副本的副本。
M[1] = [3, 4]
这里修改第二项COPY
.
但是这里 M[0][1] = 2
你正在修改原始嵌套数组的一个项目,因为 [:]
没有对嵌套列表进行任何复制操作并且复制的原始列表项目不是 "simple".
警告! 在 Python 中,当它是一个列表并执行 x = y
时,更改 y
中的值会更改 x
.
这里不是按值复制,而是按引用复制。例如。
>>> x = [[1,2], [3,4]]
>>> y = x
>>> y[0][1] = 5
>>> x
[[1, 5], [3, 4]]
但是您使用 x = y[:]
进行复制的方式是正确的。 [:]
的链接是多余的。
首先让我们了解如何真正 "copy by value" 这个嵌套列表。为此,一般来说,您可以使用 copy
模块。
>>> import copy
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y[0][1] = 5
>>> x
[[1, 2], [3, 4]]
>>> y
[[1, 5], [3, 4]]
从 https://docs.python.org/3/faq/programming.html#how-do-i-copy-an-object-in-python 开始,执行 y = x[:]
与使用 copy.copy
现在回到 [:]
表示法。如果我们深入了解嵌套并查看类型:
>>> x = [[1,2], [3,4]]
>>> type(x)
<class 'list'>
>>> type(x[0])
<class 'list'>
>>> type(x[:])
<class 'list'>
>>> type(x[:][0])
<class 'list'>
>>> type(x[:][0][0])
<class 'int'>
>>> type(x[:][0][0][0])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not subscriptable
我们看到,如果我们在某些时候直接评估内部列表中的值,则整数值不是列表,因此我们无法从中获取索引。
当我们继续做时会发生什么 x[:][:][:][:][:]
,我们看到它检查允许我们继续访问列表但是 我们真的进入了嵌套列表值吗我们做 [:]
?
>>> type(x[:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:])
<class 'list'>
>>> type(x[:][:][:][:][:][:])
<class 'list'>
这里我们看到类型没有改变,如果我们查看实际值,如果我们开始复制它:
>>> x = [[1,2], [3,4]]
>>> y = copy.deepcopy(x)
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:])
>>> y
[[1, 2], [3, 4]]
>>> y = copy.deepcopy(x[:][:][:][:])
>>> y
[[1, 2], [3, 4]]
本质上,您在第一个 x[:]
访问完整列表,然后 [:]
的连续链接不完全是 accessing/traversing 嵌套循环,但是 只是重新复制复制的列表。
将 z=x[:][:]
视为:
y = x[:]
z = y[:]
现在阅读有关切片的 documentations/questions 是一个很好的观点
- https://docs.python.org/3/tutorial/introduction.html
- Understanding slice notation
要深入挖掘,您必须深入实施。 https://github.com/python/cpython/blob/master/Objects/sliceobject.c