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], ...
随机推荐
- php如何返回一个image文件
The important points is that you must send a Content-Type header. Also, you must be careful not incl ...
- Ubuntu apache 禁止目录浏览
$ sudo vim /etc/apache2/sites-enabled/000-default 将Options后面Indexes前面加上"-"表示禁止目录浏览: <Di ...
- initEvent vs initMouseEvent
var evt = document.createEvent("MouseEvents");evt.initMouseEvent("click", true, ...
- LeetCode_Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. For example, ...
- 头文件intrins.h
intrins.h 在C51单片机编程中,头文件INTRINS.H的函数使用起来,就会让你像在用汇编时一样简便. 内部函数 描述 _crol_ 字符循环左移 _cror_ 字符循环右移 _ir ...
- cmake编译(编译目标)x86或x64
if(CMAKE_CL_64) #CMAKE的内建变量,如果是true,就说明编译器的64位的,自然可以编译64bit的程序 set(ADDRESS_MODEL 64) set(NODE_TAR ...
- Eclipse + CDT + YAGARTO + J-Link,STM32开源开发环境搭建与调试
Eclipse+CDT+YAGARTO+J-Li:开源开发环境搭建与调试:作者:Chongqing:邮箱:ycq.no1@163.com:文档版本:V1.0:发布日期:2014-08-04:前言:此文 ...
- 极简AWR报告收集指导
1.以oracle用户登录oracle数据库,执行如下命令登录数据库: sqlplus / as sysdba 2.运行如下命令: @?/rdbms/admin/awrrpt.sql 3.出现如下信息 ...
- hdu 4585 Shaolin_set用法
题目链接 题意:有n个人想成为少林,但是成为少林必须跟少林的大师大一场,当然要选择战斗力很近的,有两大师战斗力跟那人相近程度一样就选战斗力小的那个,按输入顺序,先输入的人先成为少林大师,后面输入的人, ...
- error Infos