如果我在Python中有这样的对象列表:
li = [obj1, obj2, obj3, ob4, obj5]
我将最后两个对象再次附加到列表的末尾:
li.extend(li[-2:])
li
中的重复内容现在具有相同或不同的地址吗?如果我对已附加到列表li
末尾的数组中的一个元素进行更改,那么最后的副本是否也会更改?如果是这样,是否有更好的方法来预制此副本?
答案 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
您会注意到,附加的最后两个元素确实是内存中的相同对象,因为它们分配了变量c
和d
。这意味着对列表中的最后两个对象进行更改也会更改索引2 和 3处的对象。
现在,如果您想添加最后两个元素的副本,可以执行以下操作:
extend_elements = [copy.deepcopy(i) for i in li[-2:]]
li.extend(extend_elements)
请参阅Python's copy module doc了解复制操作。