切片嵌套列表

时间:2016-11-22 15:23:51

标签: python list slice

这是一个非常愚蠢的问题,但我真的很困惑。 请看看我的代码:

>>> my_list = [1, 2, 3]
>>> my_list_new = my_list[:]
>>> my_list_new[0] = 100
>>> my_list_new
[100, 2, 3]
>>> my_list
[1, 2, 3]

所以它应该工作。我复制了my_list。当我更改my_list_new时 - 只更改了一个列表。

现在看这里:

>>> my_list2 = [[1, 2, 3], [4, 5, 6]]
>>> my_list_new2 = my_list2[:]
>>> my_list_new2[0][0] = 100
>>> my_list_new2
[[100, 2, 3], [4, 5, 6]]
>>> my_list2
[[100, 2, 3], [4, 5, 6]]

正如您所看到的,我更改了my_list_new2,但两个列表都已更改。嵌套列表是否是正常的Python行为?如何避免呢?

4 个答案:

答案 0 :(得分:1)

这应该按预期工作

my_list_new2 = [list[:] for list in my_list2]

证明

my_list2 = [[1, 2, 3], [4, 5, 6]]
my_list_new2 = [list[:] for list in my_list2]
my_list_new2[0][0] = 100

my_list_new2
[[100, 2, 3], [4, 5, 6]]

my_list2
[[1, 2, 3], [4, 5, 6]]

答案 1 :(得分:1)

列表在python中是可变的。含义:

a = [1,2,3]
b = a
a[0] = 4
print(b)

将打印[4, 2, 3]

因此,在嵌套列表的情况下,您只复制“外部”列表,并修改内部列表,因此您也将修改其他列表。如果你对python中的这个查找列表指针感兴趣

解决方案:

my_list2 = [[1, 2, 3], [4, 5, 6]]
my_list_new2 = [inner_lst.copy() for inner_lst in my_list2] # You can use inner_lst[:] as well
my_list_new2[0][0] = 100
print(my_list2)

返回:[[1, 2, 3], [4, 5, 6]]

答案 2 :(得分:-1)

列表列表(在您的情况下为l1 = [[1, 2, 3], [4, 5, 6]])包含对象(列表)。

列表的切片是列表中该子集的新浅层副本,它将引用插入到对象中。从以下代码段中可以看出。

l1 = [[1, 2, 3], [4, 5, 6]]
l2 = l1[:]

print(id(l1))       # 4406414512
print(id(l2))       # 4382080248

# Shallow copy, insert references
print(id(l1[0]))    # 4439177768
print(id(l2[0]))    # 4439177768

要复制所有内容,请使用copy.deepcopy插入对象的副本。从中可以看出,

import copy

l1 = [[1, 2, 3], [4, 5, 6]]
l2 = copy.deepcopy(l1)

l2[0][0] = 100

print(l1)   # [[1, 2, 3], [4, 5, 6]]
print(l2)   # [[100, 2, 3], [4, 5, 6]]

答案 3 :(得分:-1)

您的外部列表my_list2包含 的其他两个列表的引用。

即使您在外部列表my_list2中创建了一个独立的副本,它仍然(最初)包含相同的项目,即对相同的两个列表的相同引用。 (如果你熟悉C / C ++,你可以将引用列表作为指针松散地思考。)这就是所谓的“浅拷贝”。以下是创建浅拷贝的几种方法:

my_new_list2 = list(my_list2)
my_new_list2 = [item for item in my_list2]
my_new_list2 = my_list2[:]
import copy; my_new_list2 = copy.copy(my_list2)

要获得所需的行为,您还需要复制内部列表。您可以像其他人建议的那样手动执行此操作 - 或者您可以让Python标准库自动执行此操作。这就是copy.deepcopy的用途:

import copy
my_list_new2 = copy.deepcopy(my_list2)

deepcopy的优势在于它可以在任意数量的嵌套级别下工作,而不一定只是第一个内部级别。