吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4567|回复: 18
收起左侧

[Python 转载] 说说python下的赋值,深拷贝与浅拷贝

[复制链接]
hijack 发表于 2017-6-14 19:26
本帖最后由 hijack 于 2017-6-14 19:28 编辑

初学python的朋友一定会遇到过这个问题:
[Asm] 纯文本查看 复制代码
n1=123
n2=n1
n1=456
n2=?

今天就针对这个问题详细说一说赋值,深拷贝与浅拷贝
python的深拷贝浅拷贝需要分两方面来说:字符串与数字类型;其他数据类型
首先看看字符串与数字类型
对于字符串与数字类型:赋值,深拷贝,浅拷贝都是一回事儿,不用区别
[Python] 纯文本查看 复制代码
import copy
# 数字、字符串
n1 = 123
print(id(n1)) #id方法的返回值就是对象的内存地址

​n2 = n1 #这是赋值
print(id(n2)) 

n3 = copy.copy(n1) #这是浅拷贝
print(id(n3))    

n4 = copy.deepcopy(n1) #这是深拷贝
print(id(n3))

我们来查看下n1,n2,n3,n4的内存地址,如下图

无标题1.png
无标题2.png
对于字符串和数字来说,都一样,都是返回同一个内存地址,我们再来看看其他数据类型:
1、赋值,就是再创建个变量,指向原来内存地址
[Python] 纯文本查看 复制代码
n1 = {"k1": "hi", "k2": 123, "k3": ["hijack", 678]}  
n2 = n1

此时的id(n1)=id(n2)和上面字符串一样
​ 无标题3.png
2、浅拷贝
浅拷贝,顾名思义,很浅呐,那么就是只是在内存中只额外创建第一层数据
[Python] 纯文本查看 复制代码
import copy
n1 = {"k1": "hi", "k2": 123, "k3": ["hijack", 678]}  
n2 = copy.copy(n1)
print(id(n1),id(n2))

我们来看看内存地址
无标题4.png
和赋值不同,浅拷贝的内存地址并不相同,看看图解释下

无标题5.png
看看,是不是很浅,只创建第一层
3、深拷贝
深拷贝,顾名思义,很深呐,深到什么程度?深到除了最后一层,其余都重新创建一份(python内部对字符串和数字的优化)
[Python] 纯文本查看 复制代码
import copy
n1 = {"k1": "hi", "k2": 123, "k3": ["hijack", 678]}  
n2 = copy.deepcopy(n1)
print(id(n1),id(n2))

同样n1和n2指向的内存地址肯定不一样,看看画图解释:

无标题6.png
以上就是一些关于赋值,深拷贝浅拷贝的知识了,说的有什么不周到的还请多多指正
如果觉得觉得这篇文章对你有一点点作用的话,还请给个免费评分

免费评分

参与人数 5吾爱币 +6 热心值 +5 收起 理由
lovehhf + 1 + 1 我很赞同!
大萌黑 + 1 + 1 当初确实困扰了好久,自己鼓捣了半天才弄懂
夏雨微凉 + 1 + 1 多谢楼主分享经验,学到了
55555555 + 2 + 1 可以看出来用心了
小青年78 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

rexyan 发表于 2017-6-20 21:32
楼主说得已经很好了。下面,我自己补充点吧!

1,浅拷贝,没有拷贝到子对象。所以原始数据改变,没有被拷贝到的子对象会改变
[Python] 纯文本查看 复制代码
 i1={'k3': ['hijack', 678], 'k2': 123, 'k1': 'hi'}
 import copy
 i2=copy.copy(i1)
 i3=copy.deepcopy(i1)


现在改变原数据(最外层的),因为深拷贝和浅拷贝都涉及到了这一层,所以这一层的数据改变,不会影响拷贝的内容
[Python] 纯文本查看 复制代码
>>> i1["k4"]="add_data_test"
>>> i2
{'k3': ['hijack', 678], 'k2': 123, 'k1': 'hi'}
>>> i3
{'k3': ['hijack', 678], 'k2': 123, 'k1': 'hi'}
>>> i1
{'k3': ['hijack', 678], 'k2': 123, 'k1': 'hi', 'k4': 'add_data_test'}


现在改变原数据(最内层的),因为深拷贝没有涉及到这一层,所以浅拷贝的结果会受到影响,而深拷贝的话,里面的对象也是被拷贝了的,所以值不会被改变
[Python] 纯文本查看 复制代码
>>> i1["k3"].append("k3_test")
>>> i1
{'k3': ['hijack', 678, 'k3_test'], 'k2': 123, 'k1': 'hi', 'k4': 'add_data_test'}
>>> i2
{'k3': ['hijack', 678, 'k3_test'], 'k2': 123, 'k1': 'hi'}
>>> i3
{'k3': ['hijack', 678], 'k2': 123, 'k1': 'hi'}
>>>


总结:copy.copy()这个方法得到的对象是新对象,但是数据还是引用。
如果要完全得到一个新的一模一样的对象,要用copy.deepcopy()方法。这样,在改变新对象的时候,原对象才能不受影响,也就是保持原始数据不变
 楼主| hijack 发表于 2017-6-14 23:46
夏雨微凉 发表于 2017-6-14 21:23
这么说的话 python里边的变量是指针变量?比如 n2=n1,那么n1内容变了n2也会跟着变?

不会的,如果n1内容变了,比如变成n1=666,会另外出来一个内存地址装666,n1指向666的地址,n2还是指向原来的地址
zz0147 发表于 2017-6-14 20:18
{:1_912:}
python用的不多,希望看到你更多 的作品。
谢谢分享。
夏雨微凉 发表于 2017-6-14 21:23
这么说的话 python里边的变量是指针变量?比如 n2=n1,那么n1内容变了n2也会跟着变?
6767 发表于 2017-6-14 23:16 来自手机
LZ这里有些时候可能要解释一下小整数缓冲区和字符串缓冲区会更好
瓦特蜀黍 发表于 2017-6-15 11:03
前排留名。膜败
micksoft 发表于 2017-6-15 11:55
有种说法是“传值类型与传址类型”,跟这个说的一样吧
夏雨微凉 发表于 2017-6-15 12:24
hijack 发表于 2017-6-14 23:46
不会的,如果n1内容变了,比如变成n1=666,会另外出来一个内存地址装666,n1指向666的地址,n2还是指向原 ...

哦,原来是这样
lxj12328 发表于 2017-6-17 17:47
谢谢分享。我也刚学
webboy89860 发表于 2017-6-17 19:53
看图的话可以使用:http://pythontutor.com/ 可视化观看python内的对象方法。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lovehhf + 1 + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 23:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表