看看这个Python代码:
a = [1, 2, 3]
b = [4, 5, 6]
c = [[a, b], [b, a]] # [[[1, 2, 3], [4, 5, 6]], [[4, 5, 6], [1, 2, 3]]]
c[0][0].append(99) # [[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3, 99]]]
Run Code Online (Sandbox Code Playgroud)
请注意修改一个元素如何修改c到处.也就是说,如果99附加到c[0][0],则也附加到c[1][1].我猜这是因为Python巧妙地引用了相同的对象 for c[0][0]和c[1][1].(那是他们的id()是一样的.)
问题:是否可以执行某些操作以c使其列表元素可以安全地进行本地修改?上面只是一个例子,我的真正问题有一个更复杂的列表,但有类似的问题.
(对不起,上面提到的问题很糟糕.Python大师请随意修改问题或标签以更好地表达此查询.)
当你想要一个副本时,你明确地制作一个副本 - [:]密码"切片全部"形式是惯用的,但我最喜欢的是显式调用的更易读的方法list.
如果c以错误的方式构造(使用引用而不是浅层副本到列表,您希望能够独立修改),最好的方法是修复它的构建方式(为什么构建错误然后用来修复它?!) ,但如果这超出了您的控制范围,则可以撤消损坏 - 只需循环c(如果需要,递归),使用索引,将相关子列表重新分配给其副本.例如,如果您确定c结构是指定的两级结构,则可以在不递归的情况下保存自己:
def fixthewronglymadelist(c):
for topsublist in c:
for i, L in enumerate(topsublist):
topsublist[i] = list(L)
Run Code Online (Sandbox Code Playgroud)
尽管其他答案提出了什么copy.deepcopy,但如果给出的所有内容都是错误的,那就很难屈服于这个特殊的目的c:只是copy.deepcopy(c)谨慎地复制c的拓扑结构,包括对同一个子列表的多次引用!:-)
要将现有列表列表转换为无共享列表,可以递归复制列表.
deepcopy是不够的,因为它会按原样复制结构,保留内部引用作为引用,而不是副本.
def unshared_copy(inList):
if isinstance(inList, list):
return list( map(unshared_copy, inList) )
return inList
alist = unshared_copy(your_function_returning_lists())
Run Code Online (Sandbox Code Playgroud)
请注意,这假定数据作为列表列表(任意嵌套)返回.如果容器具有不同的类型(例如,numpy数组,dicts或用户类),则可能需要更改它.
用途[:]:
>>> a = [1, 2]
>>> b = a[:]
>>> b.append(9)
>>> a
[1, 2]
Run Code Online (Sandbox Code Playgroud)
改变,使用copy或deepcopy:
>>> import copy
>>> a = [1, 2]
>>> b = copy.copy(a)
>>> b.append(9)
>>> a
[1, 2]
Run Code Online (Sandbox Code Playgroud)
copy适用于列表以外的对象.对于列表,它具有相同的效果a[:].deepcopy尝试以递归方式复制嵌套元素,因此是一种更"彻底"的操作copy.
| 归档时间: |
|
| 查看次数: |
10356 次 |
| 最近记录: |