python考点-赋值、拷贝

赋值:只复制对象的引用,不会开辟新的内存空间。其中一个被改变的时候,另一个也会被改变。

浅拷贝:创建新的对象,其内容是原对象的引用。

浅拷贝有三种形式:切片,工厂函数,copy模块中的copy函数。

举例:

lst = [1, 2, 3, 4]

# 切片
lc = lst[:]
lc = [item for item in lst]

# 工厂函数
lc = list(lst)

# copy函数
lc = copy.copy(lst)

浅拷贝只拷贝对象的第一层(最外层) ,内部元素拷贝的是引用。

浅拷贝分两种情况:

(1)当浅拷贝的值是不可变对象(元组,字符串,数值类型)时和“赋值”一样,对象的id值和原对象的id值相同。

(1)当浅拷贝的值是可变对象(列表,字典,集合)时,分两种情况:

内部元素都是不可变对象,浅拷贝的id值与原对象不同,改变其中一个的值不会影响另一个。

内部元素有可变对象,称这些元素为复杂子对象,如果改变复杂子对象的值,会影响另一个。

一、列表

赋值:赋值后的变量id值和原对象id值相同,改变其中一个会影响另一个。

lst = [1, 2, 3, 4]

lc = lst

print(id(lst) == id(lc))  # true

浅拷贝:创建新的对象,其id值和原对象id值不同,改变其中一个不会影响另一个。

# 切片
lst = [1, 2, 3, 4]
lc = lst[:]
print(id(lst) == id(lc))  # false

# 对象的copy
lc = lst.copy()
print(id(lst) == id(lc))  # false

# copy模块的copy
from copy import copy
lc = copy(lst)
print(id(lst) == id(lc))  # false

 浅拷贝:创建新的对象,其id值和原对象id值不同,如果内部元素有可变对象(不可哈希的),改变可变对象的值会影响另一个。

from copy import copy
lst = [[5, 6], 2, 3, 4]
lc = copy(lst)
print(id(lst) == id(lc))  # false
lc[0].append(999)
print('lst:{}'.format(lst))  # lst:[[5, 6, 999], 2, 3, 4]
print('lc:{}'.format(lc))  # lc:[[5, 6, 999], 2, 3, 4]

但是,如果把内部的可变对象替换为新的对象,而不是修改其值,则不会影响原对象。

st = [[5, 6], 2, 3, 4]

# 对象的copy
lc = copy(lst)
lc[0] = [0,1]
print(id(lst) == id(lc))  # false
print('lst:{}'.format(lst))  # lst:[[5, 6], 2, 3, 4]
print('lc:{}'.format(lc))  # lc:[[0, 1], 2, 3, 4]

深拷贝:创建新的对象 ,其id值和原对象id值不同,改变其中一个不会影响另一个。

from copy import deepcopy
lst = [[5, 6], 2, 3, 4]

lc = deepcopy(lst)
lc[0].append(999)

print(id(lst) == id(lc))  # false
print('lst:{}'.format(lst))  # lst:[[5, 6], 2, 3, 4]
print('lc:{}'.format(lc))  # lc:[[5, 6, 999], 2, 3, 4]

二,字符串

字符串是不可变对象,赋值,浅拷贝,深拷贝操作不会改变id值。

s = 'hello'
t = s
print(t is s)  # true
t += 'L'  # t指向新的对象
print(s, t) # hello helloL
print(t is s)  # false  

 三、元组

元组中不含可变对象时,赋值,浅拷贝,深拷贝操作不会改变id值。

a = (1, 2, 3)
b = a
print(a is b)  # true
b += (999,)  # b指向新的对象
print(a, b)  # (1, 2, 3) (1, 2, 3, 999)
print(a is b)  # false

元组中含有可变对象时,赋值,浅拷贝后的变量修改可变对象的值,会影响原对象。

a = (1, [4,5], 3)
b = a
print(a is b)  # true
b[1].append(999)
print(a, b) #  (1, [4, 5, 999], 3) (1, [4, 5, 999], 3)
print(a is b)  # true

 元组中含有可变对象时,深拷贝后的变量修改可变对象的值,不会影响原对象。

from copy import copy,deepcopy
a = (1, [4,5], 3)
b = deepcopy(a)  # false
print(a is b)
b[1].append(999)
print(a, b)  # (1, [4, 5], 3) (1, [4, 5, 999], 3)
print(a is b)  # false

 四、集合

 赋值操作不会改变id值,其中一个改变会影响另一个。

a = {1, 2, 3}
b = a
print(a is b)  # true
b.add(999)
print(a, b)  # {1, 2, 3, 999} {1, 2, 3, 999}
print(a is b)  # true

浅拷贝会改变id值,其中一个改变不会影响另一个。

from copy import copy
a = {1, 2, 3}
b = copy(a)
print(a is b)  # false
b.add(999)
print(a, b)  # {1, 2, 3} {1, 2, 3, 999}
print(a is b)  # false

 集合中的元素都是可哈希的,列表不可哈希,所以集合中不能有列表。

五、字典

赋值操作不会改变id, 其中一个改变会影响另一个。

a = {'a': 1, 'b': 2}
b = a
print(a is b)  # true
b['a'] += 1
print(a, b)  # {'a': 2, 'b': 2} {'a': 2, 'b': 2}
print(a is b)  # true

浅拷贝会改变id值,其中一个改变不会影响另一个。

a = {'a': 1, 'b': 2}
b = a.copy()
print(a is b)  # false
b['a'] += 1
print(a, b)  # {'a': 1, 'b': 2} {'a': 2, 'b': 2}
print(a is b)  # false

但是 如果键对应的值中有可变对象,改变可变对象的值会影响原对象。

a = {'a': [4, 5], 'b': 2}
b = a.copy()
print(a is b)  # false
b['a'].append(1) 
print(a, b)  # {'a': [4, 5, 1], 'b': 2} {'a': [4, 5, 1], 'b': 2}
print(a is b)  # false

深拷贝:创建新的对象 ,其id值和原对象id值不同,改变其中一个不会影响另一个。 

from copy import deepcopy
a = {'a': [4, 5], 'b': 2}
b = deepcopy(a)
print(a is b)  # false
b['a'].append(1)
print(a, b)  # {'a': [4, 5], 'b': 2} {'a': [4, 5, 1], 'b': 2}
print(a is b)  # false

总结:不可变类型对象,没有拷贝的说法,即使使用深拷贝,查看id值也是一样的,如果对其重新赋值,新的对象会替换掉旧的对象。

一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值