将列表切片附加回原始列表只是复制地址吗?

时间:2016-07-20 18:44:48

标签: python list copy

如果我在Python中有这样的对象列表:

li = [obj1, obj2, obj3, ob4, obj5]

我将最后两个对象再次附加到列表的末尾:

li.extend(li[-2:])

li中的重复内容现在具有相同或不同的地址吗?如果我对已附加到列表li末尾的数组中的一个元素进行更改,那么最后的副本是否也会更改?如果是这样,是否有更好的方法来预制此副本?

2 个答案:

答案 0 :(得分:3)

相同的地址 - 您可以使用id进行检查。如果列表的元素是可变的,那么修改一个元素将修改另一个元素。如果列表的元素是不可变的,那么你就无法修改它们。

li = [1, 1.0, None, ['a', 'b'], ('c', 'd')]

li.extend(li[-2:])
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a', 'b'], ('c', 'd')]

li[-2].pop()
print(li)
# outputs [1, 1.0, None, ['a'], ('c', 'd'), ['a'], ('c', 'd')]
# Note that elemnts at indices -2 and -4 have changed since id(li[-2]) == id(li[-4])

print(id(li[-1]) == id(li[-3]))
# True

要添加深层副本,您可以使用copy module

li = [1, 1.0, None, ['a', 'b'], ('c', 'd')]

li.extend(list(map(copy.deepcopy, li[-2:])))
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a', 'b'], ('c', 'd')]

li[-2].pop()
print(li)
# outputs [1, 1.0, None, ['a', 'b'], ('c', 'd'), ['a'], ('c', 'd')]
# Note that only the list at index -2 has changed since id(li[-2]) != id(li[-4])

请注意,对于不可变对象,copy.deepcopy不会复制该对象,除非该对象具有对其他可变对象的引用。所以在最后一个列表id(li[-1]) == id(li[-3])

答案 1 :(得分:1)

是的,如果你以这种方式使用extend()方法,python将引用内存中的同一个对象,如果这是你想要的结果,那么只需执行:

li.extend(li[-2:])

示例:

a = object()
b = object()
c = object()
d = object()
# Alternatively a, b, c, d = object(), object(), object(), object()
li = [a, b, c, d]

现在我们查看我们的列表li

[<object object at 0x7fb84a31e0b0>, 
<object object at 0x7fb84a31e0c0>, 
<object object at 0x7fb84a31e0d0>,  # c
<object object at 0x7fb84a31e0e0>]  # d

li上运行您的操作,通知内存地址':

[<object object at 0x7fb84a31e0b0>, 
<object object at 0x7fb84a31e0c0>, 
<object object at 0x7fb84a31e0d0>,
<object object at 0x7fb84a31e0e0>, 
<object object at 0x7fb84a31e0d0>,  # <- Same object as c
<object object at 0x7fb84a31e0e0>]  # <- Same object as d

您会注意到,附加的最后两个元素确实是内存中的相同对象,因为它们分配了变量cd。这意味着对列表中的最后两个对象进行更改也会更改索引2 3处的对象。

现在,如果您想添加最后两个元素的副本,可以执行以下操作:

extend_elements = [copy.deepcopy(i) for i in li[-2:]]
li.extend(extend_elements)

请参阅Python's copy module doc了解复制操作。