你好,游客 登录 注册 搜索
背景:
阅读新闻

关于 Python 深拷贝与浅拷贝

[日期:2017-07-28] 来源:Linux社区  作者:bigberg [字体: ]

Python的数据结构总体分为两类:

1、字符串和数字

2、列表、元组、字典等

一、字符串和数字

  对于字符串和数字而言,赋值(=)、浅拷贝(copy)和深拷贝(deepcopy)其实都没有意义,因为它们都永远指向同一个内存地址。

>>> import copy
>>> a1 = 100
>>> id(a1)
1426656816  # a1的内存地址
 
# 赋值
>>> a2 = a1
>>> id(a2)
1426656816
 
# 浅拷贝
>>> a3 = copy.copy(a1)
>>> id(a3)
1426656816
 
# 深拷贝
>>> a4 = copy.deepcopy(a1)
>>> id(a4)
1426656816

  如图: 

 

 

二、列表、元组、字典等

  对于列表、字典而言,进行赋值(=)、浅拷贝(copy)和深拷贝(deepcopy),其引起的变化是不一样的。

2.1、赋值(=) 

names = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]
name2 = names
names[1] = "Pear"
print(names)
print(name2)
print("-----------------")
names[3][1] = "Dog"
print(names)
print(name2)
print(id(names))
print(id(name2))
 
 
# 输出
['Angle', 'Pear', 'Athena', ['Banana', 'apple']]
['Angle', 'Pear', 'Athena', ['Banana', 'apple']]
-----------------
['Angle', 'Pear', 'Athena', ['Banana', 'Dog']]
['Angle', 'Pear', 'Athena', ['Banana', 'Dog']]
1504387406536
1504387406536
 
# 可以看到names 的每一次变化,name2也会改变,因为他们的内存地址是一样的

  如图:

  

  这和字符串和数字是不一样的,当我们定义 a =1 ,b = a ,改变a时,b是不会有变化的。列表和字典等会跟着变化,因为他们的内存地址是一样的。  

a = 1
b =
a = 100
print(a)
print(b)
 
# 输出
 
100
1  

2.2、浅拷贝(copy) 

import copy
 
names = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]
name2 = copy.copy(names)
names[1] = "宙斯"
print(names, "names的内存地址是{}".format(id(names)))
print(name2, "name2的内存地址是{}".format(id(name2)))
 
#输出
['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的内存地址是1764417452744
['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的内存地址是1764416035080
 
我们浅copy了一个name2,同时我们将names中的Zous的值改为中文,但是name2的没有改变。因为他们的内存地址是不一样的,改变其中一个不影响另外一个。

  我们接下来看:

import copy
 
names = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]
name2 = copy.copy(names)
names[1] = "宙斯"
print(names, "names的内存地址是{}".format(id(names)))
print(name2, "name2的内存地址是{}".format(id(name2)))
 
names[3][1] = '苹果'
print(names, id(names[3]))
print(name2, id(name2[3]))
 
# 输出
['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的内存地址是2306153560776
['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的内存地址是2306152155528
['Angle', '宙斯', 'Athena', ['Banana', '苹果']] 2306153648968
['Angle', 'Zous', 'Athena', ['Banana', '苹果']] 2306153648968
 
# 这次我们不仅改变了最外层的列表的值,还改变了列表中一个列表的值。
# 这次的结果是  里层的列表跟着做了改变

  我们通过打印的内存地址可以明显看出,整个外层列表的内存地址是不一样的,但是里层的列表内存地址是一致的。

       如图:

  

  总结:浅拷贝(copy.copy(x))只是将列表等数据类型的第一层copy了一下,内存地址改变了。但是对于里层的数据类型的内存地址没有改变。

 

2.3、深拷贝(deepcopy)

  深拷贝(copy.deepcopy(x))其实就是重新开辟了一个新的内存地址,存储deepcopy后的数据,和原来数据的内存地址完全不一样了,包括里层数据类型的内存地址。 

import copy
 
names = ['Angle', 'Zous', 'Athena', ['Banana', 'apple']]
name2 = copy.deepcopy(names)
names[1] = "宙斯"
print(names, "names的内存地址是{}".format(id(names)))
print(name2, "name2的内存地址是{}".format(id(name2)))
 
names[3][1] = '苹果'
print(names, id(names[3]))
print(name2, id(name2[3]))
 
#输出
['Angle', '宙斯', 'Athena', ['Banana', 'apple']] names的内存地址是2379824216776
['Angle', 'Zous', 'Athena', ['Banana', 'apple']] name2的内存地址是2379824217160
['Angle', '宙斯', 'Athena', ['Banana', '苹果']] 2379824304968
['Angle', 'Zous', 'Athena', ['Banana', 'apple']] 2379824305032
 
#可以看出,names不论是改变外层还是里层列表的数据,都不会影响到name2。

  如图:

  

本文永久更新链接地址http://www.linuxidc.com/Linux/2017-07/145945.htm

linux
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款