python中的对象拷贝
python中。进行函数參数传递或者返回值时,假设是一般的变量,会拷贝传递。假设是列表或字典则是引用传递。那python怎样对列表和字典进行拷贝传递呢:标准库的copy模块提供了两个方法:copy和deepcopy方法。
1. copy.copy 浅拷贝 仅仅拷贝父对象,不会拷贝对象的内部的子对象。
2. copy.deepcopy 深拷贝 拷贝对象及其子对象
见下例:
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象 e = a[:] #利用分片操作进行拷贝(浅拷贝)
b = a #赋值。传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝 a.append(5) #改动对象a
a[4].append('c') #改动对象a中的['a', 'b']列表子对象 print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
执行结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
e = [1, 2, 3, 4, ['a', 'b', 'c']]
分析:
b是a的一个引用。两者指向的对象同样,打印结果必定同样。c仅仅拷贝了a的中的父对象。对于a中嵌套的子对象列表并没有拷贝,所以c中的1,2,3,4是拷贝得到的副本,属于自己的,但嵌套的子对象列表还是a原来的。d的话,因为是深拷贝,所以子对象父对象都是拷贝生产的新的副本。全然不所原来a的影响。至于e,分片操作的效果等价于浅拷贝,结果和c同样。
以下以列表为例,看看函数參数传递和返回值中,是怎样进行引用传递的:
#coding=utf-8
def ggg():
l = [1, 2, 3] #局部变量
print 'local var ', l return l def fff(l):
l.append(100)
l[2].append('c') print "global var ", l #全局变量 return l a = ggg()
print a
a.append(10)
print a
ggg() print '\n\n' a = [1, 2, ['a', 'b'], 3]
b = fff(a)
print a
b.append(1000)
print b
print a
执行结果:
local var [1, 2, 3]
[1, 2, 3]
[1, 2, 3, 10]
local var [1, 2, 3]
global var [1, 2, ['a', 'b', 'c'], 3, 100]
[1, 2, ['a', 'b', 'c'], 3, 100]
[1, 2, ['a', 'b', 'c'], 3, 100, 1000]
[1, 2, ['a', 'b', 'c'], 3, 100, 1000]
分析:
a接受函数ggg返回的局部变量。但改动a后第二次调用函数ggg,ggg内的局部变量l并没有受到影响,课件ggg返回局部变量时是拷贝传递,就像C++中的一样:函数不可能返回局部变量的引用,由于局部变量保存在函数的栈空间中,函数调用结束后,栈被销毁。不能够对局部变量进行引用了。
将a传递给函数fff后。a被改变了。说明进行了引用传递;函数fff的返回值赋给b。对b的改动也会影响到a,说明返回值也是进行的引用传递(只是这里返回的可不是局部变量了)。
另外,字典还有自己的copy方法。但没有deepcopy方法。其copy方法和上面的copy模块中的copy方法一样,也是实现的浅拷贝。
另一点:对于一般变量,假设想达到引用传递的效果,怎么办呢?python标准库中并没有提供类似C++中专门的引用或指针的机制,要实现函数内部对传入变量的改动有两种途径:
1、通过函数返回值又一次赋值变量。
2、将变量封装在列表中在传给函数。
最后一点:把一个类的对象传递给函数的时候,类似引用传递,在函数内部改动类的变量。会真正改变其值。见下例:
class TestClass(object):
val1 = 100 #类变量 def __init__(self):
self.val2 = 200 #成员变量 def change(obj):
obj.val2 = 5555
obj.val1 = 6666 if __name__ == '__main__': inst0 = TestClass()
print '$$$ ',inst0.val1 #100
print '$$$ ',inst0.val2 #200 change(inst0) print '*** ',inst0.val1 #6666
print '*** ',inst0.val2 #5555
python中的对象拷贝的更多相关文章
- 【转】python中的对象拷贝
转自:https://www.cnblogs.com/bhlsheji/p/5352330.html python中.进行函数參数传递或者返回值时,假设是一般的变量,会拷贝传递.假设是列表或字典则是引 ...
- 天啦噜!仅仅5张图,彻底搞懂Python中的深浅拷贝
Python中的深浅拷贝 在讲深浅拷贝之前,我们先重温一下 is 和==的区别. 在判断对象是否相等比较的时候我们可以用is 和 == is:比较两个对象的引用是否相同,即 它们的id 是否一样 == ...
- Python 中的深浅拷贝
Python 中的深浅拷贝 参考文献:https://blog.csdn.net/lnotime/article/details/81194633 参考文献:https://blog.csdn.net ...
- Java 开发中的对象拷贝
前言 在 Java 开发中,很多时候需要将两个属性基本相同的对象进行属性复制,比如 DO 转 VO等等. 本文主要介绍自己实现的简易拷贝工具类与 Spring 提供的属性拷贝的对比. Spring 提 ...
- python中生成器对象和return 还有循环的区别
python中生成器对象和return 还有循环的区别 在python中存在这么一个关键字yield,这个关键字在项目中经常被用到,比如我写一个函数不想它只返回一次就结束那我们就不能用return,因 ...
- PyObject and PyTypeObject - Python 中的 '对象' 们
1 PyObject, PyTypeObject - Python 中的 '对象' 们 '一切皆对象' - 这是 Python 的学习和使用者们最最常听到一句, 可谓 博大精深 - '勃大精深'. ' ...
- Python中的深浅拷贝
1.什么是深浅拷贝? python中一切皆对象,python中的数字.字符串.元组等,如果存放在了内存中,这部分内存里面的内容是不会改变的,但是也有情况,内存中存放了可变对象,比如说列表和字典,他们的 ...
- Python中的深浅拷贝,赋值及引用
简单来说,若对象a中存的是列表或字典等可变对象,b对a的浅拷贝只是对对象第一层的复制,修改b第二层的元素仍然会影响两个对象. 深拷贝则是不会影响原来的对象. import copy.copy() 浅拷 ...
- Python基础【3】:Python中的深浅拷贝解析
深浅拷贝 在研究Python的深浅拷贝区别前需要先弄清楚以下的一些基础概念: 变量--引用--对象(可变对象,不可变对象) 切片(序列化对象)--拷贝(深拷贝,浅拷贝) 我是铺垫~ 一.[变量--引用 ...
随机推荐
- RubyCritic:一款不错的检测代码质量工具
关注代码质量是高效开发必须要做的一件事,那么在 Ruby 开发的过程中,是否有什么好的代码质量检测工具呢?下面由 Ruby 工程师路英瑞介绍一下 RubyCritic--一款还不错的代码质量检测工具. ...
- python:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xef in position xxx: ordinal not in range(128)
执行sql_cmd = "select * from item_base where item_id in " + item_ids_str时报错 solve: import sy ...
- HDU3367+并查集应用
题意:找到一个这样的图,在这个图中,最多有一个环. 使得所有的边的和最大. 贪心+并查集 首先把边排序,然后开始分类讨论. 对于边ab(含有两个端点ab) 如果a,b是属于两个不同的集合 a b 是两 ...
- PHP file_exists() 函数
定义和用法 file_exists() 函数检查文件或目录是否存在. 如果指定的文件或目录存在则返回 true,否则返回 false. 语法 file_exists(path) 参数 描述 path ...
- 李洪强漫谈iOS开发[C语言-021]-运算符
- 转:为什么Eclipse中 按 F3 无效
通常是由于自己的 工程 建得不对, 没有声明为 JAVA 或 PHP 类型工程. 例如, PHP 工程的 .project 文件中的内容如果如下, F3 应该就可以起作用了. <?xml ver ...
- Android开发UI之常用控件的使用
1.日期选择控件 DatePickerDialog 代码: btnChooseDate=(Button) findViewById(R.id.btnChooseDate); btnChooseDate ...
- c语言main函数的参数argc,argv说明
main函数参数argc,argv说明 C/C++语言中的main函数,经常带有参数argc,argv,如下: int main(int argc, char** argv) int main(i ...
- Objective-C 记录
NSdata 与 NSString,Byte数组,UIImage 的相互转换 原文网址:http://www.cnblogs.com/jacktu/archive/2011/11/08/2241528 ...
- 【转】win7 旗舰版激活密钥
原文网址:http://zhidao.baidu.com/question/1496641289562471179.html 旗舰版KH2J9-PC326-T44D4-39H6V-TVPBYTFP9Y ...