以下是小编帮大家整理的Python中的赋值、浅拷贝、深拷贝介绍(共含5篇),仅供参考,大家一起来看看吧。同时,但愿您也能像本文投稿人“易长乐”一样,积极向本站投稿分享好文章。
这篇文章主要介绍了Python中的赋值、浅拷贝、深拷贝介绍,Python中也分为简单赋值、浅拷贝、深拷贝这几种“拷贝”方式,需要的朋友可以参考下
和很多语言一样,Python中也分为简单赋值、浅拷贝、深拷贝这几种“拷贝”方式,
在学习过程中,一开始对浅拷贝理解很模糊。不过经过一系列的实验后,我发现对这三者的概念有了进一步的了解。
一、赋值
赋值算是这三种操作中最常见的了,我们通过一些例子来分析下赋值操作:
str例
代码如下:
>>>a = ‘hello‘
>>>b = ‘hello‘
>>>c = a
>>>[id(x) for x in a,b,c]
[440410, 4404120000, 4404120000]
由以上指令中,我们可以发现a, b, c三者的地址是一样的。所以以上赋值的操作就相当于c = a = b = ‘hello‘。
赋值是系统先给一个变量或者对象(这里是‘hello‘)分配了内存,然后再将地址赋给a, b, c。所以它们的地址是相同的。
list例
代码如下:
>>>a = [‘hello‘]
>>>b = [‘hello‘]
>>>c = a
>>>[id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
但是这种情况却不一样了,a和b的地址不同。为何?
因为str是不可变的,所以同样是‘hello‘只有一个地址,但是list是可变的,所以必须分配两个地址。
这时,我们希望探究以上两种情况如果 修改值 会如何?
str例
代码如下:
>>>a = ‘world‘
>>>[id(x) for x in a,b,c]
[4404120432, 4404120000, 4404120000]
>>>print a, b, c
world hello hello
这时a的地址和值变了,但是b, c地址和值都未变。因为str的不可变性,a要重新赋值则需重新开辟内存空间,所以a的值改变,a指向的地址改变。b, c由于‘hello‘的不变性,不会发生改变。
list例
代码如下:
>>>a[0] = ‘world‘
>>>[id(x) for x in a,b,c]
[4403975952, 4404095096, 4403975952]
>>>print a, b, c
[‘world‘] [‘hello‘] [‘world‘]
这时a, c的值和地址均改变,但二者仍相同,b不改变。由于list的可变性,所以修改list的值不需要另外开辟空间,只需修改原地址的值。所以a, c均改变。
在了解了以上的不同点之后,我们就能很好地分析浅拷贝和深拷贝了。
我们均用list作为例子。
二、浅拷贝
代码如下:
>>>a = [‘hello‘, [123, 234]]
>>>b = a[:]
>>>[id(x) for x in a,b]
[4496003656, 4496066752]
>>>[id(x) for x in a]
[4496091584, 4495947536]
>>>[id(x) for x in b]
[4496091584, 4495947536]
Line3,4可以看出a, b地址不同,这符合list是可变的,应开辟不同空间,
那浅拷贝就是拷贝了一个副本吗?再看Line5 - 8,我们发现a, b中元素的地址是相同的。如果说字符串‘hello‘地址一致还能理解,但是第二个元素是list地址仍一致。 这就说明了浅拷贝的特点,只是将容器内的元素的地址复制了一份 。
接着我们尝试修改a, b中的值:
代码如下:
>>>a[0] = ‘world‘
>>>a[1].append(345)
>>>print ‘a = ‘, a, ‘\n\r‘, ‘b = ‘, b
a = [‘world‘, [123, 234, 345]]
b = [‘hello‘, [123, 234, 345]]
a中第一个元素str改变,但是b中未改变;a中第二个元素改变,b中也改变。这就符合不可变的对象修改会开辟新的空间,可变的对象修改不会开辟新空间。也进一步证明了 浅拷贝仅仅是复制了容器中元素的地址 。
三、深拷贝
代码如下:
>>>from copy import deepcopy
>>>a = [‘hello‘, [123, 234]]
>>>b = deepcopy(a)
>>>[id(x) for x in a, b]
[4496066824, 4496066680]
>>>[id(x) for x in a]
[4496091584, 4496067040]
>>>[id(x) for x in b]
[4496091584, 4496371792]
深拷贝后,可以发现a, b地址以及a, b中元素地址均不同。这才是完全 拷贝了一个副本 。
修改a的值后:
代码如下:
>>>a[0] = ‘world‘
>>>a[1].append(345)
>>>print ‘a = ‘, a, ‘\n\r‘, ‘b = ‘, b
a = [‘world‘, [123, 234, 345]]
b = [‘hello‘, [123, 234]]
从Line4,5中可以发现仅仅a修改了,b没有任何修改。 因为b是一个完全的副本,元素地址均与a不同,a修改,b不受影响 。
总结:
1. 赋值是将一个对象的地址赋值给一个变量,让变量指向该地址( 旧瓶装旧酒 )。
2. 浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素( 新瓶装旧酒 )。
3. 深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。也就是说( 新瓶装新酒 )。
这篇文章主要介绍了Python中使用copy模块实现列表(list)拷贝,本文讲解了简单列表的复制和复杂列表复制的解决方法,需要的朋友可以参考下
引用是指保存的值为对象的地址,在 Python 语言中,一个变量保存的值除了基本类型保存的是值外,其它都是引用,因此对于它们的使用就需要小心一些。下面举个例子:
问题描述:已知一个列表,求生成一个新的列表,列表元素是原列表的复制
代码如下:
a=[1,2]
b=a
这种做法其实并未真正生成一个新的列表,b指向的仍然是a所指向的对象。这样,如果对a或b的元素进行修改,a,b的值同时发生变化。
解决的方法为:
代码如下:
a=[1,2]
b=a[:]
这样修改a对b没有影响。修改b对a没有影响。
但 这种方法只适用于简单列表,也就是列表中的元素都是基本类型,如果列表元素还存在列表的话,这种方法就不适用了。原因就是,象a[:]这种处理,只是将列 表元素的值生成一个新的列表,如果列表元素也是一个列表,如:a=[1,[2]],那么这种复制对于元素[2]的处理只是复制[2]的引用,而并未生成 [2]的一个新的列表复制。为了证明这一点,测试步骤如下:
代码如下:
>>>a=[1,[2]]
>>>b=a[:]
>>>b
[1, [2]]
>>>a[1].append(3)
>>>a
[1, [2, 3]]
>>>b
[1, [2, 3]]
可见,对a的修改影响到了b,
如果解决这一问题,可以使用copy模块中的deepcopy函数。修改测试如下:
代码如下:
>>>import copy
>>>a=[1,[2]]
>>>b=copy.deepcopy(a)
>>>b
[1, [2]]
>>>a[1].append(3)
>>>a
[1, [2, 3]]
>>>b
[1, [2]]
有时候知道这一点是非常重要的,因为可能你的确需要一个新的列表,并且对这个新的列表进行操作,同时不想影响原来的列表。
作者:DarkBull 字体:[增加 减小] 类型:
这篇文章主要介绍了举例区分Python中的浅复制与深复制,是Python入门学习中的重要知识,需要的朋友可以参考下
copy模块用于对象的拷贝操作,该模块非常简单,只提供了两个主要的方法: copy.copy 与 copy.deepcopy ,分别表示浅复制与深复制。什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍。复制操作只对复合对象有效。用简单的例子来分别介绍这两个方法。
浅复制只复制对象本身,没有复制该对象所引用的对象。
#coding=gbkimport copyl1 = [1, 2, [3, 4]]l2 = copy.copy(l1)print l1print l2l2[2][0] = 50print l1print l2#---- 结果 ----[1, 2, [3, 4]][1, 2, [3, 4]][1, 2, [50, 4]][1, 2, [50, 4]]
同样的代码,使用深复制,结果就不一样:
import copyl1 = [1, 2, [3, 4]]l2 = copy.deepcopy(l1)print l1print l2l2[2][0] = 50print l1print l2#---- 结果 ----[1, 2, [3, 4]][1, 2, [3, 4]][1, 2, [3, 4]][1, 2, [50, 4]]
改变copy的默认行为
在定义类的时候,通过定义__copy__和__deepcopy__方法,可以改变copy的默认行为,
下面是一个简单的例子:
class CopyObj(object): def __repr__(self): return “CopyObj” def __copy__(self): return “Hello”obj = CopyObjobj1 = copy.copy(obj)print objprint obj1#---- 结果 ----CopyObjHello
-04-04python模拟登陆阿里妈妈生成商品推广链接
-09-09Python strip lstrip rstrip使用方法
-03-03python 字符串split的用法分享
2013-11-11python二叉树的实现实例
2013-11-11教你安装python Django(图文)
2014-04-04python判断、获取一张图片主色调的2个实例
2014-05-05Python getopt模块处理命令行选项实例
2014-01-01使用scrapy实现爬网站例子和实现网络爬虫(蜘蛛)的步骤
-01-01Python Mysql数据库操作 Perl操作Mysql数据库
2013-11-11linux环境下安装pyramid和新建项目的步骤
python中精确输出JSON浮点数的方法
python中关于日期时间处理的问答集锦
linux系统使用python监测系统负载脚本分享
python用字典统计单词或汉字词个数示例
python调用windows api锁定计算机示例
python教程之用py2exe将PY文件转成EXE文件
python 获取本机ip地址的两个方法
python 测试实现方法
python使用cookielib库示例分享
python中的对象拷贝示例 python引用传递
Python入门教程 超详细1小时学会
python 中文乱码问题深入分析
比较详细Python正则表达式操作指
Python字符串的encode与decode研
Python open读写文件实现脚本
Python enumerate遍历数组示例应
Python 深入理解yield
Python+Django在windows下的开发
python 文件和路径操作函数小结
python 字符串split的用法分享
★ 拷贝不走样作文