python变量在内存中是这样存储的:
在python中,一切都是对象,对象的存储是引用存储,存储的只是变量的值所在的内存地址,而不是这个变量的值本身。
如果对值进行修改,其实是在内存中新创建一个值,把变量指向这个值的地址
可以看出地址发生了改变
如果是两个值相等,那么改变其中一个不会影响另一个
a=b时a,b指向同一个地址
改变a的值后b不会改变
说明是在内存中新创建了一个值,a指向了这个值的地址
这是基本类型的存储
python中可以分两大类数据类型,一种是基础数据类型,如 int str float,long ,bool等基础类型,另一种是list,tulpe,dict,set等复杂类型,list,tulpe,dict,set中包含基础类型
由于python中的变量都是采用的引用存储,而list,tuple,dict这种数据结构可以包含基础数据类型,这就导致了每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只是每个元素的地址而已。
如果是list列表的存储形式:
L = [1,2,3,'a','b','c']
print(id(L))
变量L的地址为
每个元素的地址为
L = [1,2,3,'a','b','c']
#print(id(L))
print(id(L[0]))
print(id(L[1]))
print(id(L[2]))
print(id(L[3]))
print(id(L[4]))
L所存的就是这些元素的地址
在内存表现形式为:
将列表L的内容赋值给另一个变量和字符的操作一样
L = [1,2,3,'a','b','c']
Y = L
print(L)
print(Y)
print(id(L))
print(id(Y))
对L追加元素:
L = [1,2,3,'a','b','c']
Y = L
print(L)
print(Y)
print(id(L))
print(id(Y))
L.append("f")
print(L)
print(Y)
print(id(L))
print(id(Y))
如果重新赋值或者说重新初始化,那么会重新分配新的内存空间
L = [1,2,3,'a','b','c']
Y = L
print(L)
print(Y)
print(id(L))
print(id(Y))
L.append("f")
print(L)
print(Y)
print(id(L))
print(id(Y))
L = ['a','b','c']
print(L)
print(Y)
print(id(L))
print(id(Y))
也就是说如果在地址上操作那么指向这两个地址的变量的内容都会改变但是地址指向不变
如果重新赋值,那么重新赋值的那个变量地址就会指向新的内存地址
这就是变量赋值的过程
浅拷贝
浅拷贝:不管多么复杂的数据结构,浅拷贝都只会copy一层。
基础数据的拷贝,不管浅拷贝还是深拷贝都一样都会重新分配内存地址
#基础数据拷贝
import copy
L = [1,2,3,'a','b']
M = copy.copy(L)
print(L)
print(M)
print(id(L))
print(id(M))
import copy
L = [1,2,3,'a','b']
M = copy.copy(L)
print(L)
print(M)
print(id(L))
print(id(M))
#给L追加一个元素M不会变
L.append("c")
print(L)
print(M)
print(id(L))
print(id(M))
深拷贝基础数据:
import copy
L = [1,2,3,'a','b']
M = copy.deepcopy(L)
print(L)
print(M)
print(id(L))
print(id(M))
#给L追加一个元素M不会变
L.append("c")
print(L)
print(M)
print(id(L))
print(id(M))
结果和浅拷贝一样
复杂的数据:
仅仅对外层修改拷贝后L改变M不变
import copy
L = [1,2,[3,4,'c','d'],'a','b']
M = copy.copy(L)
print(L)
print(M)
print(id(L))
print(id(M))
#给L追加一个元素M不会变
L.append("c")
print(L)
print(M)
print(id(L))
print(id(M))
对内层改变,那么拷贝后都会变
import copy
L = [1,2,[3,4,'c','d'],'a','b']
M = copy.copy(L)
print(L)
print(M)
print(id(L))
print(id(M))
L[2].append("e")
print(L)
print(M)
print(id(L))
print(id(M))
这说明对内层数据的修改会改变另一个拷贝的对象
在内存中的形式为:
上图可以看出,内层list[1,2]也是一个地址,里面存的就是元素1,2的地址
所以对L的内层操作就是对内层list[1,2]地址的操作,这样就会改变M
深度拷贝:
import copy
L = [1,2,[3,4,'c','d'],'a','b']
M = copy.deepcopy(L)
print(L)
print(M)
print(id(L))
print(id(M))
#给L追加一个元素M不会变
L[2].append("e")
print(L)
print(M)
print(id(L))
print(id(M))
可以看出L改变M不变
在内存中的形式:
相当于所有的都拷贝一份
1、对于复杂的数据结构copy.copy 浅拷贝 只拷贝父对象(最外一层),不会拷贝对象的内部(内层数据)的子对象。
2、copy.deepcopy 深拷贝 拷贝父对象(外层数据)及其子对象(内层数据)
3、对于基本数据类型深拷贝浅拷贝都一样,都会产生新的数据空间
原文地址:http://blog.51cto.com/linuxubuntu/2087773