Shallow Copy & Deep Copy in Python list
2014-09-12 16:51
295 查看
今天在写一个小程序的时候用到了2维数组, 顺手就写成了[[0.0]*length]*length, 结果为了这个小错,调试了半个多小时,
其实之前对与浅复制和深复制已经做过学习和总结, 但真正编程用到这些知识时还是掉入了陷阱中. 所以在此做进一步的总结:
本文通过几个实例来说明Python中list的深复制和浅复制:
a[0].append(1)后, 如果a的输出结果让你感到有些困惑,你可以参考这里(原因是Python中的*运算采用的是浅复制).
同样的道理,下面的代码我们应该都能够理解:
让我们一起来分析一下:
对于a(理解为一个2维数组)中的每一个元素都是一个list(理解为一个1维数组), 但我们需要注意的是a的每一个元素
a[0],a[1],a[2]...指向的是同一段内存区域(浅复制),所以更改(修改值或添加值)任何一个元素(a[0]或a[1]...a[9])都会直接影
响到其它的元素.
如何验证a中的每一个元素a[0], a[1],...,a[9]指向同一段内存区域? 可以通过id方法来验证:
注意:虽然a的每一个元素a[0],a[1],a[2]...指向的是同一段内存区域,但a中的各个元素是独立的元素(他们相同但不同一),
也就是说删除掉任何一个数据对其他的数据没有任何影响:
那么应该怎么实现深复制呢?其实在前面提到的文章中已经介绍了这一方法:
至此, 我觉得还有一点需要说明:
一定要理解*操作的对象是谁, 例如: [2]*10得到[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], *10操作的对象是[]中的2, 也就是说*10操
作使list中的元素2复制10次. 同理[[]]*10得到[[], [], [], [], [], [], [], [], [], []],*10操作的对象是[]中的[], 也就是说*10
操作使list中的元素[]浅复制10次, 这10个空list指向内存中相同的区域(参见上面用id验证部分).
下面用2段代码作为对比列出来, 便于查看:
其实之前对与浅复制和深复制已经做过学习和总结, 但真正编程用到这些知识时还是掉入了陷阱中. 所以在此做进一步的总结:
本文通过几个实例来说明Python中list的深复制和浅复制:
>>> a = [[]] * 10 >>> a [[], [], [], [], [], [], [], [], [], []] >>> a[0][0] = 10 #NO WAY Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list assignment index out of range >>> a[0].append(1) >>> a [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
a[0].append(1)后, 如果a的输出结果让你感到有些困惑,你可以参考这里(原因是Python中的*运算采用的是浅复制).
同样的道理,下面的代码我们应该都能够理解:
>>> a[3].append(9) >>> a [[1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9], [1, 9]] >>> a[2][1] = 3 >>> a [[1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]
让我们一起来分析一下:
对于a(理解为一个2维数组)中的每一个元素都是一个list(理解为一个1维数组), 但我们需要注意的是a的每一个元素
a[0],a[1],a[2]...指向的是同一段内存区域(浅复制),所以更改(修改值或添加值)任何一个元素(a[0]或a[1]...a[9])都会直接影
响到其它的元素.
如何验证a中的每一个元素a[0], a[1],...,a[9]指向同一段内存区域? 可以通过id方法来验证:
>>> id.__doc__ "id(object) -> integer Return the identity of an object. This is guaranteed to be unique among simultaneously existing objects. (Hint: it's the object's memory address.)"
>>> a = [[]]*10 >>> a [[], [], [], [], [], [], [], [], [], []] >>> id(a[0]) 3071938316L >>> id(a[1]) 3071938316L >>> a[0].append(1) >>> a [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]] >>> id(a[0]) 3071938316L >>> id(a[1]) 3071938316L >>>
注意:虽然a的每一个元素a[0],a[1],a[2]...指向的是同一段内存区域,但a中的各个元素是独立的元素(他们相同但不同一),
也就是说删除掉任何一个数据对其他的数据没有任何影响:
>>> a = [[]] * 10 >>> a [[], [], [], [], [], [], [], [], [], []] >>> a[0].append(1) >>> a [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]] >>> len(a) 10 >>> del(a[2]) >>> a [[1], [1], [1], [1], [1], [1], [1], [1], [1]] >>> len(a) 9
那么应该怎么实现深复制呢?其实在前面提到的文章中已经介绍了这一方法:
>>> c = [[] for i in range(10)] >>> c [[], [], [], [], [], [], [], [], [], []] >>> c[0].append(3) >>> c [[3], [], [], [], [], [], [], [], [], []] >>>
至此, 我觉得还有一点需要说明:
一定要理解*操作的对象是谁, 例如: [2]*10得到[2, 2, 2, 2, 2, 2, 2, 2, 2, 2], *10操作的对象是[]中的2, 也就是说*10操
作使list中的元素2复制10次. 同理[[]]*10得到[[], [], [], [], [], [], [], [], [], []],*10操作的对象是[]中的[], 也就是说*10
操作使list中的元素[]浅复制10次, 这10个空list指向内存中相同的区域(参见上面用id验证部分).
下面用2段代码作为对比列出来, 便于查看:
>>> a = [2] * 10 >>> a [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] >>> id(a[0]) 164067492 >>> id(a[1]) 164067492 >>> a[0] = 1 #NOTE >>> id(a[0]) #NOTE 164067504 >>> id(a[1]) 164067492 >>>
>>> b = [[]] * 10 >>> b [[], [], [], [], [], [], [], [], [], []] >>> id(b[0]) 3072965964L >>> id(b[1]) 3072965964L >>> b[0].append(10) >>> id(b[0]) 3072965964L >>> id(b[1]) 3072965964L >>> b [[10], [10], [10], [10], [10], [10], [10], [10], [10], [10]] >>> b[0][0] = 1 >>> b [[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]] >>> id(b[0]) 3072965964L >>> id(b[1]) 3072965964L >>> b[0] = [10] >>> b [[10], [1], [1], [1], [1], [1], [1], [1], [1], [1]] >>> id(b[1]) 3072965964L >>> id(b[0]) 3072965996L >>>
相关文章推荐
- Deepin Linux Desktop, 截图工具剖析(五) python - lambda, list, dictionary
- difference between str & list in python
- [Python]Shallow and Deep copy operation
- C++类中的4个特殊函数 && Object copy (Deep vs. Shallow vs. Lazy copy)
- python copy & deepcopy 区别
- [Python] List & Object spread in Python
- python deep copy and shallow copy
- Python: Shallow and deep copy operations
- difference between Python shallow copy and deep copy
- python写代码实现list的deepcopy
- make a copy of list in python
- shallow copy and deep copy in Prototype Pattern
- python copy & deepcopy 区别
- Python Shallow Copy VS. Deep Copy (Python浅拷贝和深拷贝)
- Python: Shallow and deep copy operations
- python copy & deepcopy 区别
- 【转】.NET深入学习笔记(4):深拷贝与浅拷贝(Deep Copy and Shallow Copy)
- Python入门的36个例子 之 26 -> File In Console Out
- C# Tips-浅拷贝和深拷贝(shallow copy VS deep copy )
- Python 去除List的回车'/n'