Python是一门很好的语言,他的优点在于拥有巨大灵活性的同时也拥有无比的严谨性,其他语言规定了很多语法,告诉你什么情况下,语法就是这样的,而Python却用很少的规定,延伸出很多语法,有些语法看上去很奇怪,仔细分析却是那么的合理。今天思考了Python中关于指针和深浅复制的问题,下面希望能通过根据内存空间的变化对这些让人头疼的问题作出一个解释。
首先看第一个例子:
a = 1
b = a
b = 2
print ’a = %s‘ %a, ‘b = %s’%b
结果:a = 1 b = 2
当执行a = 1操作时,内存中先分配一个整型变量的空间并赋值为1,然后将a指向这块空间,执行b = a时,将b也指向这块内存,这时,a和b的地位是一样的。b = 2,按说会把当前b指向的那块内存赋值为2,其实Python并不会这样做。因为在Python中,整型以及其他基本类型加上字符串和元组等是不可以被修改的。意思是他们一旦被声明,在内存上就不能被改变。那么执行b = 2时发生的是,系统分配一个整型的内存,并赋值为,再将这块内存的地址赋给b,因此a和b就指向了不同的值。
在看一个很矛盾的例子:
a=[1,[2],3]
b=a
b[0]=0
print a
结果:[0,[2],3]
这好像不太对,和上面说的有点矛盾,其实并不矛盾。因为列表是可以修改的,a和b指向的是一个列表,其实列表时存的是一组指针。指针是可以修改的。元组不能修改就是因为元组里的数据是内存上的数据本身,而列表里元素是指针。当使用b修改b[0]时,实际上是将原本指向一个1的指针b[0]同时也是a[0]指向了一个0,而那个1如果没有别的指针指向他的话,他就被回收了。这个0和1虽然索引一样,但在内存中的位置不同。我无比的希望可以打印指针的内容来验证我的想法。
内存情况如下:
赋值之后:
下面说一下copy()和deepcopy()。
deepcopy()就不用说了,这个就是严格的深复制。两个指针一点关系都没有,谁也不会影响谁,因为他们在内存中是独立的。而copy就不行了,他是copy()有别于直接赋值,但它又不同于deepcopy()。举个例子:
import copy
a=[1,[2],3]
b=copy.copy(a)
b[0]=0
b[1].append(2)
print a
结果为:[1,[2,2],3]
折结果看似意外,其实是十分合理的。copy()是一种浅复制,b实际上是a的一个影子,系统也为b分配了自己的空间,意味着a和b指向的内存并不相同,但是,b中只复制了a中的指针,意思是b的每一项和a中的每一项指向的内存是相同的。当对b[0]赋值为0时,b[0]从指向1改为指向0,而a[0]还是指向1的,因此a的第一项仍为1。而b[1].append(2)时,b[1]和a[1]指向同一个列表,这个列表就是[2]。这条语句并没有修改指针而是让[2]增加了一个元素。a[1]和b[1]还是指向这个列表的。因此a[1]变为[2,2]。画一下的话应该是这个样子:
上图是copy()过后的内存情况。经过操作后内存的情况如下:
上面v就是我对Python内存管理和指针的理解。如有错误,请指正。
原文地址:http://blog.csdn.net/u010352695/article/details/44458365