python内存相关以及深浅拷贝讲解

3.9 内存相关

3.9.1 id,查看内存地址

>>> v1 = [11,22,33]
>>> v2 = [11,22,33]
>>> print(id(v1),id(v2)) # 比较两个变量的内存值
4472652360 4473773640	
# 对于 -5 ~ 256 的整数来说会有小地址池的概念,不会创建新的内存地址
>>> v1 = "我,你,他,它,她"
>>> v2 = "我,你,他,它,她"
>>> print(id(v1),id(v2))
4473666128 4473665840
 # 赋值,就是把v2指向了v1的内存地址,所以他们的内存地址一样
>>> v1 = "我,你,他,它,她"
>>> v2 = v1 
>>> print(id(v1),id(v2))
4473666128 4473666128

# 重新赋值,v1的内存地址变了,但是v2的内存地址没变
>>> v1 = "我,你,他,它,她"
>>> v2 = v1    
>>> v1 = "我,你,他,它,她,天"   v1现在指向"我,你,他,它,她,天"的地址,v2还是原来的
>>> print(id(v1),id(v2))
4473665840 4473666128
>>> print(v2)
我,你,他,它,她

is,比较内存地址

>>> v1 = {'k1':'v1','k2':[1,2,3]}
>>> v2 = {'k1':'v1','k2':[1,2,3]}
>>> result1 = v1 == v2
>>> result2 = v1 is v2
>>> print(result1)
True
>>> print(result2)
False

重要

is 和 == 的区别?

== 用于比较值是否相等。
is 用于比较内存地址是否相等。

PS:找到内存地址并在其中做操作和赋值 不一样

重新赋值是重新开辟一块内存空间、可变数据类型

#练习1(内部修改)
v1=[11,22,33]
v2=v1
v1.append(666)
print(v2) #含有666

#练习2(赋值)
v1=[11,22,33]
v2=v1
v1=[1,2,3,4] #此时v1重新赋值为[1,2,3,4],v1=[11,22,33] 对应的内存地址被回收,只要有指向这个内存地址的,就不会被回收
print(v2) #[11,22,33]

#练习3(重新赋值) 
v1='alex'
v2=v1
v1='old boy'
print(v2) #'alex'

总结:可变数据类型列表/字典/集合 有内部修改和赋值
字符串等不可变的 只有重新赋值(不可在内部修改)

ps:
v=[1,2,3]
value=[11,22,v]
value[2]=666 #对value自己更改,v不会改变
print(v)  #[1, 2, 3]

v=[1,2,3]
value=[11,22,v]
value[2][0]=666 #对v里面修改,v会改变
print(v)  #[666, 2, 3]

python中有小数据池--缓存机制,节省内存

  1. 数字 (-5-256)
  2. 简单的字符串 ‘ALEX’
a=1
b=1
print(id(a),id(b)) #496846480 496846480  #理论上赋值,是重新开辟内存地址,但python中有缓存机制

3.10 深浅拷贝

浅拷贝:只拷贝第一层。浅copy会仅复制dict的第一层数据,更深层的scores下面的值依然是共享一份

深拷贝:拷贝所有数据(只针对可变数据类型)--- 重新拷贝意味着重新在内存中开辟一块空间,都是独立的内存地址

只有一层的深拷贝意义不大,重要的是对于嵌套

1、int+str+bool/tuple 深浅拷贝是一样的(不可变数据类型,类似小数据池的概念)

v1='alex'
v2=copy.copy(v1)
v3=copy.deepcopy(v1)
print(id(v1),id(v3)) #11611168 11611168
2、list+set+dict (可变数据类型)
深浅拷贝不一样的

总结

浅拷贝:仅会拷贝a的框架的内存地址, 里面的任何子元素的内存地址都不会被拷贝.
深拷贝:不仅拷贝a的框架,而且会拷贝a里所有的可变元素的内存地址,注意不可变元素仍不可拷贝
posted @ 2019-09-09 17:43  hanfe1  阅读(315)  评论(0编辑  收藏  举报