Python - shallow copy and deepcopy

# author
# date 2022/5/10 - 10:13

# difference between '==' and 'is'
# "==" compare the value of an object
# "is" judge two variable is the same , id(variable)

a = 10
b = 10
print(a == b)  # True
print(a is b)  # True

print(id(a))   # 140737281630896
print(id(b))   # 140737281630896

# 对于不可变对象, 例如,字符或元组
t1 = (1, 2, [3, 4])  # 元组对象中包含可变元素-列表
t2 = (1, 2, [3, 4])

print(t1 == t2)   # True
print(t1 is t2)   # False

t1[-1].append(5)
print(t1)  # (1, 2, [3, 4, 5])
#  说明虽然元组对象是不可变的,但是里面还有可变对象的元素,
#  可以修改元组元素

"""
shallow copy and deep copy
shallow copy : 浅拷贝,是指重新分配一块内存,创建一个新的对象,
里面的元素是源对象中子对象的引用。因此,如果源对象中的元素不可变,对浅拷贝出的新对象无影响
但是,要注意,浅拷贝通常会有一些副作用
可以通过list(), tuple(), set(),dict() 等函数实现对象的浅拷贝
也可以通过切片[:] 实现对象的浅拷贝
"""

l1 = [1, 2, 3]
l2 = list(l1)
print(l2)  # [1, 2, 3]
print(l1 == l2)  # True
print(l1 is l2)  # False

s1 = {1, 2, 3}
s2 = set(s1)
print(s2)  # {1, 2, 3}
print(s2 == s1)  # True
print(s2 is s1)  # False

# 说明: l2 is the shallow copy of l1
#  s2 is the shallow copy of s1

l1 = [1, 2, 3]  # True
l2 = l1[:]  # False 对于可变序列,可以通过切片“:“ 完成浅拷贝
print(l1 == l2)
print(l2 is l1)

# 元组对象
t1 = (1, 2, 3)
t2 = t1[:]
print(t2 is t1)   # True
# 对于元组,使用tuple()或切片操作符[:] 不会创建一份浅拷贝
# 相反,它会返回一个指向相同元组的引用

# python中提供了响应的函数 copy.copy(),实现对象的浅拷贝,适用于任何数据类型
import copy
l1 = [1, 2, 3]
l2 = copy.copy(l1)
print(l2 is l1)  # False

#  浅拷贝的一些副作用
l1 = [[1, 2], [30, 40]]
l2 = copy.copy(l1)
l1.append(100)  # 对l1列表新增元素,该操作对l2无影响
l1[0].append(3)
print(l1)  # [[1, 2, 3], [30, 40], 100]
print(l2)  # [[1, 2, 3], [30, 40]]

l1[1] += (50, 60)  # 由于元组是不可变的,对列表l1中的第二个元组对象拼接,
# 然后创建了一个新元组作为l1中的第二个元素, 而l2中没有引用新元组,
# 因此l2不受影响
# 此处 元组的+=操作可以类比字符的+=操作,

s = "my name"
print(id(s))
s = s + ' is'
print(id(s))
print(s)  # 其中s的改变并不是真正的修改了s变量,而是重新创建了一个s变量

print(l1)  # [[1, 2, 3], [30, 40, 50, 60], 100]
print(l2)  # [[1, 2, 3], [30, 40]]

# 上述代码,初始化了一个列表l1,里面的元素低一个列表和一个元组;
# 然后对l1指向浅拷贝,赋予l2, 因为浅拷贝里的元素是对源对象的引用,
# 因此l2中的元素和l1指向同一个列表和元组对象




#  深拷贝 l2 是 l1 的深拷贝对象,l2与l1之间完全独立
l1 = [[1, 2], [30, 40]]
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)
print(l1)  # [[1, 2, 3], [30, 40], 100]
print(l2)  # [[1, 2], [30, 40]]

l1[1] += (30, 40)
print(l1)  # [[1, 2, 3], [30, 40, 30, 40], 100]
print(l2)  # [[1, 2], [30, 40]]

# 深度拷贝并不是完美的,如果被copy对象中存在指向自身的引用,程序容易陷入无限循环
x = [1]
x.append(x)  # [1, [...]]
print(x)

y = copy.deepcopy(x)
print(y)   # [1, [...]]






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值