python 赋值,浅拷贝,深拷贝
感谢前辈:学习连接
总结:
本文介绍了对象的赋值和拷贝,以及它们之间的差异:
- Python中对象的赋值都是进行对象引用(内存地址)传递
- 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
- 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
- 对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有被拷贝一说
- 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子
图片总结:
注意上面深拷贝中,39774408的wiber中,"will", "28"地址不变,因为他们是原子类型,没有拷贝一说,但是其中的list,很明显深拷贝的中的["Python", "C#", "JavaScript"]对象,在新的地址空间中整个复制了一块,跟原来没关系了。
代码:
# @TIME : 2019/3/30 下午2:14
# @File : 浅拷贝-深拷贝.py
# 对象赋值操作!
print('--对象赋值操作--\n')
will = ["will", 28, ["python", "c#", "JavaScript"]]
wilber = will
print("will的id是",id(will))
print("wilber的id是",id(wilber))
print("will 中元素 id: ", [id(i) for i in will])
print("wilber 中元素 id: ", [id(i) for i in wilber])
print("will = ", will)
print("wilber = ", wilber)
# 修改元素
will[0] = "HAHA" #这里需要注意的一点是,str是不可变类型,所以当修改的时候会替换旧的对象
will[2].append("C++")
print('-----------------------------------------------------\n')
print("will的id是",id(will))
print("wilber的id是",id(wilber))
print("will 中元素 id: ", [id(i) for i in will])
print("wilber 中元素 id: ", [id(i) for i in wilber])
print("will = ", will)
print("wilber = ", wilber)
# 浅拷贝
print("\n--浅拷贝--\n")
import copy
a = ["will", 28, ['python', 'c#', 'JavaScript']]
b = copy.copy(a)
print("a的id是",id(a))
print("b的id是",id(b))
print("a 中元素 id: ", [id(i) for i in a])
print("b 中元素 id: ", [id(i) for i in b])
print("a = ", a)
print("b = ", b)
a[0] = 'haha'
a[2].append('c++')
print('-----------------------------------------------------\n')
print("a的id是",id(a))
print("b的id是",id(b))
print("a 中元素 id: ", [id(i) for i in a])
print("b 中元素 id: ", [id(i) for i in b])
print("a = ", a)
print("b = ", b)
# 总结一下,当我们使用下面的操作的时候,会产生浅拷贝的效果:
#
# 使用切片[:]操作
# 使用工厂函数(如list/dir/set)
# 使用copy模块中的copy()函数
# 深拷贝
print("\n--深拷贝--\n")
a = ["will", 28, ['python', 'c#', 'JavaScript']]
b = copy.deepcopy(a)
print("a的id是",id(a))
print("b的id是",id(b))
print("a 中元素 id: ", [id(i) for i in a])
print("b 中元素 id: ", [id(i) for i in b])
print("a = ", a)
print("b = ", b)
a[0] = 'haha'
a[2].append('c++')
print('-----------------------------------------------------\n')
print("a的id是",id(a))
print("b的id是",id(b))
print("a 中元素 id: ", [id(i) for i in a])
print("b 中元素 id: ", [id(i) for i in b])
print("a = ", a)
print("b = ", b)
# 其实,对于拷贝有一些特殊情况:
#
# 对于非容器类型(如数字、字符串、和其他'原子'类型的对象)没有拷贝这一说
# 也就是说,对于这些类型,"obj is copy.copy(obj)" 、"obj is copy.deepcopy(obj)"
# 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子
结果:
--对象赋值操作--
will的id是 4559779080
wilber的id是 4559779080
will 中元素 id: [4433642920, 4431481632, 4559689416]
wilber 中元素 id: [4433642920, 4431481632, 4559689416]
will = ['will', 28, ['python', 'c#', 'JavaScript']]
wilber = ['will', 28, ['python', 'c#', 'JavaScript']]
-----------------------------------------------------
will的id是 4559779080
wilber的id是 4559779080
will 中元素 id: [4439464848, 4431481632, 4559689416]
wilber 中元素 id: [4439464848, 4431481632, 4559689416]
will = ['HAHA', 28, ['python', 'c#', 'JavaScript', 'C++']]
wilber = ['HAHA', 28, ['python', 'c#', 'JavaScript', 'C++']]
--浅拷贝--
a的id是 4559783240
b的id是 4559783176
a 中元素 id: [4433642920, 4431481632, 4559783304]
b 中元素 id: [4433642920, 4431481632, 4559783304]
a = ['will', 28, ['python', 'c#', 'JavaScript']]
b = ['will', 28, ['python', 'c#', 'JavaScript']]
-----------------------------------------------------
a的id是 4559783240
b的id是 4559783176
a 中元素 id: [4439502496, 4431481632, 4559783304]
b 中元素 id: [4433642920, 4431481632, 4559783304]
a = ['haha', 28, ['python', 'c#', 'JavaScript', 'c++']]
b = ['will', 28, ['python', 'c#', 'JavaScript', 'c++']]
--深拷贝--
a的id是 4559783048
b的id是 4559783240
a 中元素 id: [4433642920, 4431481632, 4559783112]
b 中元素 id: [4433642920, 4431481632, 4559782472]
a = ['will', 28, ['python', 'c#', 'JavaScript']]
b = ['will', 28, ['python', 'c#', 'JavaScript']]
-----------------------------------------------------
a的id是 4559783048
b的id是 4559783240
a 中元素 id: [4439502496, 4431481632, 4559783112]
b 中元素 id: [4433642920, 4431481632, 4559782472]
a = ['haha', 28, ['python', 'c#', 'JavaScript', 'c++']]
b = ['will', 28, ['python', 'c#', 'JavaScript']]
Process finished with exit code 0