python学习笔记:别名(赋值)、浅拷贝、深拷贝

前提知识:

python中变量的初始化操作执行三步:1. 开辟存储开辟一个内存空间:存储变量的地址,id(viriable);2.开辟一块内存空间(不连续),存储变量元素的地址;3.开辟一块内存空间,存储变量元素的值。

例如:a=[1,2,3],三步如下:

 


一、直接赋值 :

b=a,此时,b是a的别名,也就是说a就是b。

(1)第一种情况:

a=[1,2,3]
print("address of a is",id(a))
b=a
print("address of b is",id(b))             
a+=[4]
print("a=",a)
print("b=",b)
print("Now address of a is",id(a))
print("Now address of b is",id(b))
 

此时输出:

address of a is 171219464
address of b is 171219464
a= [1, 2, 3, 4]
b= [1, 2, 3, 4]
Now address of a is 171219464
Now address of b is 171219464

b拷贝的是变量a的地址,即id(b)=id(a),当变量a增加元素时,变量a(也是变量b)的地址(id(a))不发生改变。

(2)第二种情况:

a=[1,2,3]
print("address of a is",id(a))
b=a
print("address of b is",id(b))             
a=a+[4]
print("a=",a)
print("b=",b)
print("Now address of a is",id(a))
print("Now address of b is",id(b))
 

此时输出:

address of a is 171199984
address of b is 171199984
a= [1, 2, 3, 4]
b= [1, 2, 3]
Now address of a is 171218184
Now address of b is 171199984

这是因为,当执行a=a+[4]这条语句时,等号左边的a≠等号右边的a,即:生成了新的id(a),但id(b)=旧id(a)。

二、浅拷贝(shallow copy)

b=a.copy() or b=copy.cpoy(),仅拷贝a的父对象。即:1.开辟新空间存储变量b的地址;2.共用变量a各元素(一级元素)地址,即第一层。

(1)第一种情况:

import copy
a=[1,2,3,['alex','boby']]
b=a.copy()
print("address of a is",id(a)) 
print("address of b is",id(b))
print("id(a[3][0]) is",id(a[3][0]))
print("id(b[3][0]) is",id(b[3][0]))
a[3][0]='cindy'
print("Now address of a is",id(a))
print("Now address of b is",id(b))
print("a=",a)
print("b=",b)
print("id(a[3][0]) is",id(a[3][0]))
print("id(b[3][0]) is",id(b[3][0]))
print("id(a[3][1]) is",id(a[3][1]))
print("id(b[3][1]) is",id(a[3][1]))

此时输出:

address of a is 171514536
address of b is 171197784
id(a[3][0]) is 171277536
id(b[3][0]) is 171277536
Now address of a is 171514536
Now address of b is 171197784
a= [1, 2, 3, ['cindy', 'boby']]
b= [1, 2, 3, ['cindy', 'boby']]
id(a[3][0]) is 171277920
id(b[3][0]) is 171277920
id(a[3][1]) is 171277888
id(b[3][1]) is 171277888

执行b=a.copy(),使得id(b[0])~id(b[3])对应等于id(a[0])~id(a[3]);执行a[3][0]="cindy",则重新开辟内存空间,存储a[3][0]的地址,并重新开辟内存空间,存放"cindy",即重新对a[3][0]进行赋值。由于d(a[3])=id(b[3]),引用的是id(a[3][0])和id(a[3][1])的地址,故a与b均相应改变:

(2)第二种情况:

import copy
a=[1,2,3,['alex','boby']]
b=a.copy()
print("address of a is",id(a)) 
print("address of b is",id(b))
print("id(a[3][0]) is",id(a[3][0]))
print("id(b[3][0]) is",id(b[3][0]))
a[1]='cindy'
print("Now address of a is",id(a))
print("Now address of b is",id(b))
print("a=",a)
print("b=",b)

此时输出:

address of a is 171513936
address of b is 171514416
id(a[3][0]) is 171277536
id(b[3][0]) is 171277536
Now address of a is 171513936
Now address of b is 171514416
a= [1, 'cindy', 3, ['alex', 'boby']]
b= [1, 2, 3, ['alex', 'boby']]

执行a[0]="cindy",重新开辟内存空间,存储id(a[0]),并重新开辟内存空间,存储"cindy"。由于id(b[0])仍等于旧id(a[0]),故变量a发生改变,而变量b不发生改变。

三、深拷贝(deep copy)

b=copy.deepcopy(a),开辟一个内存空间存储变量b的地址,此后各级元素(父对象及子对象)地址均进行拷贝,因此,不论a如何变化,b均不发生改变(b引用的元素地址不变)。

import copy
# Create a 2d list
a = [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]

# Try to copy it
b = copy.deepcopy(a) # Correct!

# At first, things seem ok
print("At first...")
print("   a =", a)
print("   b =", b)
print("   id(a) is",id(a))
print("   id(b) is",id(b))
print("   id(a[0]) is",id(a[0]))
print("   id(b[0]) is",id(b[0]))
print("   id(a[0][0]) is",id(a[0][0]))
print("   id(b[0][0]) is",id(b[0][0]))
# Now modify a[0][0]
a[0][0]= 9
print("And after a[0][0] = 9")
print("   a =", a)
print("   b =", b)
print("   id(a[0]) is",id(a[0]))
print("   id(b[0]) is",id(b[0]))
print("   id(a[0][0]) is",id(a[0][0]))
print("   id(b[0][0]) is",id(b[0][0]))

此时输出:

At first...
   a = [[1, 2, 3], [4, 5, 6]]
   b = [[1, 2, 3], [4, 5, 6]]
   id(a) is 171537712
   id(b) is 171536792
   id(a[0]) is 171513736
   id(b[0]) is 171514536
   id(a[0][0]) is 1492461760
   id(b[0][0]) is 1492461760
And after a[0][0] = 9
   a = [[9, 2, 3], [4, 5, 6]]
   b = [[1, 2, 3], [4, 5, 6]]
   id(a[0]) is 171513736
   id(b[0]) is 171514536
   id(a[0][0]) is 1492461888
   id(b[0][0]) is 1492461760

浅拷贝vs.深拷贝:

         

其他:

  • 切片拷贝(b=a[:])属于浅拷贝。
  • 。。。

 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值