Python浅拷贝 深拷贝

内存泄漏太可怕。

Python 可变对象 & 不可变对象

在Python中,对象分为两种:可变对象不可变对象

  • 不可变对象包括int,float,long,str,tuple等;
  • 可变对象包括list,set,dict等

需要注意的是:这里说的不可变指的是值的不可变。对于不可变类型的变量,如果要更改变量,则会创建一个新值,把变量绑定到新值上,而旧值如果没有被引用就等待垃圾回收。另外,不可变的类型可以计算hash值,作为字典的key。可变类型数据对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请(+/-)即可,也就是它的内存地址会保持不变,但区域会变长或者变短。
如下所示:

list = [1, 2, 3]
print(id(list))
arr = [4, 5]
list = list + arr
print(id(list))

list2 = [1, 2, 3]
print(id(list2))
list2 += [4, 5]
print(id(list2))

# 输出结果:
# 4557530312
# 4557530696
# 4557530312
# 4557530312
  • list = list + arr,list出现两次,必须执行两次,性能不好,合并必须新建对象list,然后复制两个列表合并,这属于拷贝;
  • list += arr,list只出现一次,因为不生成新对象,因此性能好,只在内存块末尾增加元素。当操作元素为list时,“+=”会自动调用 extend 方法进行合并运算,这属于共享引用.

Python没有赋值,只有引用

Python中的“=”传递的是引用(内存地址),应按照C语言中的指针理解。

Python浅拷贝copy.copy()

Python中,对于非容器类型(如数字、字符串、和其他原子类型的对象)没有被拷贝一说。

使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的子对象,依然使用原始的引用,所以原始数据改变,子对象会改变。

该示例显示了通过传递引用的方式创建obj1,此时obj1 is list

list = [1, 2, 3, ['a', 'b']]
obj1 = list
# 输出list与obj1的地址
print('id of list =', id(list))
print('id of obj1 =', id(obj1))
# obj1原始的值
print('value of obj1 =', obj1)
# 修改list的值,看obj1中对应的值是否改变
list[1] = 999
print('value of obj1 =', obj1)

# 输出结果:
# id of list = 4367528520
# id of obj1 = 4367528520
# value of obj1 = [1, 2, 3, ['a', 'b']]
# value of obj1 = [1, 999, 3, ['a', 'b']]

接下来通过浅拷贝创建obj2,可以看到此时list与obj2指向了不同的地址,修改list中的字符串、布尔类型、整数、浮点数、数字不会改变obj2中的值;但是此时obj2的子对象还是与list中的子列表共享一块内存

obj2 = copy.copy(list)
# 输出list与obj2的地址
print('id of list =', id(list))
print('id of obj2 =', id(obj2))
# 输出list与obj2中每个元素的地址
print('id of list = ', [id(it) for it in list])
print('id of obj2 = ', [id(it) for it in obj2])
# 修改list[0]的值,看obj2中的值是否改变
list[0] = -1
print('value of list =', list)
print('value of obj2 =', obj2)
print('-' * 50)
# 修改list中的子列表,看obj2中的值是否改变
list[3].append('c')
print('value of obj2 =', obj2)
# 输出list与obj2中每个元素的地址
print('id of list = ', [id(it) for it in list])
print('id of obj2 = ', [id(it) for it in obj2])

# 输出结果:
# id of list = 4367528520
# id of obj2 = 4367558344
# id of list =  [4345380112, 4346236624, 4345380176, 4367558536]
# id of obj2 =  [4345380112, 4346236624, 4345380176, 4367558536]
# value of list = [-1, 999, 3, ['a', 'b']]
# value of obj2 = [1, 999, 3, ['a', 'b']]
# --------------------------------------------------
# value of obj2 = [1, 999, 3, ['a', 'b', 'c']]
# id of list =  [4345380048, 4346236624, 4345380176, 4367558536]
# id of obj2 =  [4345380112, 4346236624, 4345380176, 4367558536]

当我们使用下面的操作的时候,会产生浅拷贝的效果:

  • 使用切片[:]操作
  • 使用工厂函数(如list/dir/set)
  • 使用copy模块中的copy()函数

Python深拷贝copy.deepcopy()

复制一个容器对象,并且,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝

list = [1, 2, 3, ['a', 'b']]
obj3 = copy.deepcopy(list)
# 输出list与obj3的地址
print('id of list =', id(list))
print('id of obj3 =', id(obj3))
# 输出list与obj3中每个元素的地址
print('id of list = ', [id(it) for it in list])
print('id of obj2 = ', [id(it) for it in obj3])
# 修改list中的子列表,看obj2中的值是否改变
list[3].append('c')
# 修改list[0]的值,看obj2中的值是否改变
print('value of list =', list)
print('value of obj2 =', obj3)

# 输出结果:
# id of list = 4370554760
# id of obj3 = 4370650248
# id of list =  [4348476688, 4348476720, 4348476752, 4370650440]
# id of obj2 =  [4348476688, 4348476720, 4348476752, 4370650120]
# value of list = [1, 2, 3, ['a', 'b', 'c']]
# value of obj2 = [1, 2, 3, ['a', 'b']]

关于Python内存管理机制请见:
Python源码阅读-内存管理机制(一)
Python源码阅读-内存管理机制(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • http://python.jobbole.com/85231/ 关于专业技能写完项目接着写写一名3年工作经验的J...
    燕京博士阅读 7,540评论 1 118
  • 个人笔记,方便自己查阅使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik阅读 67,668评论 0 5
  • 在 JS 中有一些基本类型像是Number、String、Boolean,而对象就是像这样的东西{ name: '...
    tobAlier阅读 547评论 0 0
  • 原文出处:http://www.cnblogs.com/wilber2013/p/4645353.html Pyt...
    码农小杨阅读 776评论 0 6
  • 如果你遇事了, 有人风雨同舟,有人伸出援手, 感动的泪水会打湿眼窝, 这就是幸福! 如果你难过了, 有人守在身侧,...
    微笑略带伤阅读 278评论 0 0