Python中的Copy和Deepcopy
一,Python的对象:
Python存在大量的对象,我们一般提到的对象都是C中的结构体在堆中申请的一块内存(以CPython为例),每一个对象都有ID,可以通过ID(Object)获得。对象的范围包括内建类型的对象(如int类型的对象123,str的对象"test",list的对象[],生成器对象等等)、用户自建类型的对象、函数(lambda函数,生成器函数)、类型、Ture、False(bool类型的对象)、None(NoneType的对象)。
print id(123)
print id("test")
print id([])
print id(xrange(1, 3))
print id(lambda v: v)
print id(int)
print id(True)
print id(None) print type(123)
print type("test")
print type([])
print type(xrange(1, 3))
print type(lambda v: v)
print type(int)
print type(True)
print type(None)
19257680
19062656
27888896
19590176
27863344
505361888
505379788
505354444
<type 'int'>
<type 'str'>
<type 'list'>
<type 'xrange'>
<type 'function'>
<type 'type'>
<type 'bool'>
<type 'NoneType'>
猜想int类型、True和None都是在高地址中,而动态生成的都是位于低地址中。
二,Python的引用计数:
所有对象都采用引用计数,给对象分配新名词或者将其放入容器中,这个对象的引用计数都会增加。当离开作用域或者被重新赋值的时候,这个对象的引用计数就会减少。当减少为0,垃圾收集器会将其销毁。
Python中的对象分为immutable和mutabel,作为immutable的int、char和tuple,相同的值在内存中只会生成一次,每次将其赋值到变量中,便会增加一个引用计数。而作为mutable的list、dict、xrange(生成器)和lambda(函数),每次生成都会在内存中生成一个新的对象。
另外:传参的时候,若参数为mutable,则传的是引用,若参数为immutable,则传的是值。
a = 123 #创建一个值为123的对象
b = 123 #增加123的引用计数
a = 111 #创建一个值为111的对象,减少123的引用计数
b = a #增加111的引用计数 c = [] #创建一个空队列
d = [] #创建一个新的空队列
c = [] #再创建一个新的空队列,减少原队列的引用计数
c = d #增加d队列的引用计数,减少c队列的引用计数
c.append(1) #创建一个值为1的对象,不改变原队列的引用计数
三,Shallow copy和Deep copy的区别
Python document中是这么说的:
- A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
- A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
这其中的区别就是浅复制会简单的复制引用,不管他是mutable还是immutable。而深复制则会递归地复制immutable对象引用,对于mutable,则会新建一个对象。
import copy
a = [1, 2]
b = [a, 3]
c = copy.copy(b) #c = [[1, 2], 3]
d = copy.deepcopy(b) #d = [[1, 2], 3]
a.append(3) #c = [[1, 2, 3], 3]
#d = [[1, 2], 3]
四,如何控制Shallow copy和Deep copy?
在deepcopy时候,会遇到问题,比如有对象中有一个指向用户信息的列表,用户希望在复制的时候直接引用原列表。这个时候可以使用定制功能。
可以在类型中定义__copy__和__deepcopy__实现shallow copy和deep copy,当用户下次调用copy.copy和copy.deepcopy时,便会调用__copy__和__deepcopy__。
import copy
class Example(dict):
def __init__(self, needcopy={}, userinfo={}):
super(Example, self).__init__()
self.need = needcopy
self.user = userinfo def __deepcopy__(self, memo):
if memo is None:
memo = {}
result = self.__class__()
memo[id(self)] = result
for key in self.need.keys():
result.need = copy.deepcopy(self.need)
result.user = self.user
return result needcopy = {"price": 100}
userinfo = {"user": "vincent"}
a = Example(needcopy, userinfo)
b = copy.deepcopy(a)
needcopy["title"] = "no"
userinfo["passwd"] = "none"
print "need: ", a.need, "; user: ", a.user
print "need: ", b.need, "; user: ", b.user
need: {'price': 100, 'title': 'no'} ; user: {'passwd': 'none', 'user': 'vincent'}
need: {'price': 100} ; user: {'passwd': 'none', 'user': 'vincent'}
Output
Python中的Copy和Deepcopy的更多相关文章
- Python中=、copy、deepcopy
一.Python中的"=" a = 1 b = 1 c = a print(id(a)) print(id(b)) print(id(c)) #输出为 14070784103734 ...
- python中 =、copy、deepcopy的差别
python2中,需要import copy模块 python3中,直接可以使用copy()方法,但deepcopy()还是需要导入copy模块 下面以python2为例: 对于"=&quo ...
- copy模块中的copy与deepcopy的区别
前言 每空闲下来,就觉得以前写的博客很low........也许现在也很low~~~~好吧就当升级版的low吧~~~~ 如果要了解copy与deepcopy的区别,就需要了解Python的存储机制:P ...
- Python字典方法copy()和deepcopy()的区别
from copy import deepcopy # import deepcopy模块 d = {} d['name'] = ['black', 'guts'] # d = {'name': [' ...
- 深入理解Python中赋值、深拷贝(deepcopy)、浅拷贝(copy)
赋值 python跟java中的变量本质是不一样的,Python的变量实质上是一个指针(int型或str型),而java的变量是一个可操作的存储空间. a = 123b = a print(id(a) ...
- python中的copy.copy和copy.deepcopy
一个例子就搞清楚 import copy a = [1, 2, 3, 4, ['a', 'b']] #原始对象 b = a #赋值,传对象的引用 c = copy.copy(a) #对象拷贝,浅拷贝 ...
- python中深copy,浅copy
版权声明:本文为博主原创文章,未经博主允许不得转载. >>> mylist1 = [1, 2, 3, 4] >>> myl = mylist1 >>&g ...
- python中深copy,浅copy与赋值语句的区别
以下详细讲解:python深复制,浅复制与赋值语句的区别 1. '='赋值语句,常规复制只是将另一个变量名关联到了列表,并不进行副本复制,实例如下: var1=[12,35,67,91,101]var ...
- python copy与deepcopy (拷贝与深拷贝)
copy与deepcopy python 中的copy与deepcopy是内存数据的操作,但是两个函数有一定的区别. 1.copy import copy list = [1, [4, 5, 6], ...
随机推荐
- Java中,&&与&;||与|的区别
我们很多人在学习Java的时候,或者其他语言(如:C#,.Net等)都会遇到&和&&,|和||.然而,如果你没有真正理解他们的意思,这回给你的思路上带来很大的麻烦.在Java的 ...
- ECshop使用财付通接口支付时出现“[3006]您的请求无效,请重新再试
ECshop使用财付通接口支付时出现“[3006]您的请求无效,请重新再试.”解决方案\includes\modules\payment\tenpay.php 行 104原来的为 $bill_no = ...
- 给EcStore商城会员添加推广返利功能
EcStore商城后台应用中心安装“网站推广”应用,会员成为推广员有二种途径:一是后台/推广设置/推广员审核/推广注册模式设为:需注册后审核成为推广员 此模式下前台会员在使用推广前,需要在会员中心申请 ...
- mongodb 基本语法
成功启动MongoDB后,再打开一个命令行窗口输入mongo,就可以进行数据库的一些操作. 输入help可以看到基本操作命令: show dbs:显示数据库列表 show collections:显示 ...
- 为GridView中的DropDownList赋值
<Bda:GridView ID="gvMessage" runat="server" Height="70px" Width=&qu ...
- C# XmlReader/XmlWriter 类
XmlReader用于读取Xml文件,XmlWriter用于将数据写到Xml文件.其实,在印象当中,XML很多的操作类都支持直接Save.Read也支持接受XmlReader与XmlWriter类的示 ...
- 《Programming WPF》翻译 第7章 5.可视化层编程
原文:<Programming WPF>翻译 第7章 5.可视化层编程 形状元素能提供一种便利的方式与图形一起工作,在一些情形中,添加表示绘图的元素到UI树中,可能是比它的价值更加麻烦.你 ...
- hidden symbol ... is referenced by DSO
在Linux上编译Qt的时候configure出来的Makefile传递给g++的参数visiblility=hidden,然后就会调用Qt库所使用的第三方库libpng库源代码函数声明添加上__at ...
- java设计模式--行为型模式--模板方法
什么是模板方法,这个有待考虑,看下面: 模板方法 概述 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中. TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步 ...
- UML--核心元素之参与者Actor
参与者(actor):在系统之外与系统交互的某人或某事物.例如,管理员,用户等等. 参与者位于边界之外,边界之内的都不叫参与者.用一个词来形容更准确,主角.也就是只有主动启动了这个业务的人,才是参与者 ...