Python 深浅拷贝
Python浅拷贝和深度拷贝
今天面试了一个计算机专业研究生且大学出身也很好,但是面试的结果来看并没有达到我的预期。很多基础计算机的知识貌似都不是很懂,更别说对操作系统、编译原理和算法的深度造化了。不排除高级语言和IDE隐藏了很多细节,但是当你去追求更高性能或者你想进阶的话,我想说底层的东西真的很重要。只有你完全掌握这些底层的东西,你才能通过高级语言特性来优化你的业务和应用。虽然有点扯淡,还是开始咱们今天聊一下Python的浅拷贝和深度拷贝。
对象赋值
在Python中大致可以分为immutable和mutable两种数据类型,比如:字符串字面值、数字、元组等这些是immutable类型,列表、字典等是mutable类型。我们先来看一下python对象赋值是如何赋值的?
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from copy import copy,deepcopy
adr = lambda x:hex(id(x))
def test(count=None):
print"test method before id ",adr(count)
if type(count)==list:
count.append(1)
else:
count+=1
print"test method after id ",adr(count)
if __name__ == "__main__":
a,b = 1,1
c,d = [],[]
print"a,b,c,d id ",map(adr,(a,b,c,d))
print"1,1,[],[] id ",map(adr,(1,1,[],[]))
print"c=",c
test(c)
print"c=",c
print"a=",a
test(a)
print"a=",a
运行结果如下所示:
a,b,c,d id ['0x10030c0b8', '0x10030c0b8', '0x10269c488', '0x1006ea200']
1,1,[],[] id ['0x10030c0b8', '0x10030c0b8', '0x102693320', '0x10269ec68']
c= []
test method before id 0x10269c488
test method after id 0x10269c488
c= [1]
a= 1
test method before id 0x10030c0b8
test method after id 0x10030c0a0
a= 1
我们先分析一下我们所写的代码,我们新建了四个变量分别为a,b,c和d。其中都为相同的字面值或者说都是相同的object,在python一切皆对象。我们看到immutable类型是赋值操作是直接传递内存地址;而对于mutable类型,赋值操作定义一个新的对象,将右值对象内存地址传递给这个新的对象。函数参数传递是按照内存地址传递,其引用传递。
浅拷贝
我们先看一下Demmo:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from copy import copy,deepcopy
adr = lambda x:hex(id(x))
if __name__ == "__main__":
p = ['brian',25,["python"]]
p1 = copy(p)
print"p id,p1 id",map(adr,(p,p1))
print"p element id==",map(adr,p)
print"p1 element id==",map(adr,p1)
print".....change ......"
p[0]="lv"
p[1]=1111
p[2].append(12)
print"p element id==",map(adr,p)
print"p1 element id==",map(adr,p1)
运行结果如下所示:
p id,p1 id ['0x10399e320', '0x103ac5950']
p element id== ['0x103aae990', '0x10030be78', '0x1006ea200']
p1 element id== ['0x103aae990', '0x10030be78', '0x1006ea200']
.....change ......
p element id== ['0x1021bbd78', '0x102068218', '0x1006ea200']
p1 element id== ['0x103aae990', '0x10030be78', '0x1006ea200']
非常清晰的可以看到,浅拷贝对于immutable类型来说是拷贝了一个不可变的对象的引用, 修改你得到的变量只会让该变量的引用指向一个新的对象,而对于mutable类型来说还是对象引用。使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用. 看一下产生浅拷贝的效果操作:
- 使用切片[:]操作
- 使用工厂函数(如list/dir/set)
- 使用copy模块中的copy()函数
深拷贝
深拷贝是完全真正意义上的拷贝,是完全复制所有对象元素。但是对于原子类型对象(immutable)是没有深拷贝这么一说的。先来看一下例子:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from copy import copy,deepcopy
adr = lambda x:hex(id(x))
if __name__ == "__main__":
p = ['brian',25,["python"]]
p1 = deepcopy(p)
print"p id,p1 id",map(adr,(p,p1))
print"p element id==",map(adr,p)
print"p1 element id==",map(adr,p1)
print".....change ......"
p[0]="lv"
p[1]=1111
p[2].append(12)
print"p element id==",map(adr,p)
print"p1 element id==",map(adr,p1)
运行结果如下:
p id,p1 id ['0x101e93320', '0x101e9eef0']
p element id== ['0x101fab990', '0x10030be78', '0x1006ea200']
p1 element id== ['0x101fab990', '0x10030be78', '0x101e9cf38']
.....change ......
p element id== ['0x1019bbd78', '0x100733f48', '0x1006ea200']
p1 element id== ['0x101fab990', '0x10030be78', '0x101e9cf38']
deepcopy是完全意义上的copy,实现了真正的隔离。
- 除了写烂的手写数据分类,你会不会做自定义图像数据集的识别?!
- shell脚本中字符串的常见操作及"command not found"报错处理(附源码)
- 绝对定位下的盒模型
- 运行shell脚本时报错"[[ : not found"解决方法
- 关于表联结方法(二) (r4笔记第23天)
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(一)设计一套好的RESTful API
- XSS分析及预防
- 关于ORA-01779问题的分析和解决 (r4笔记第22天)
- 想看爱奇艺VIP视频?一个python脚本帮你搞定
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势
- 关于shell中的pl/sql脚本错误排查与分析(r4笔记第21天)
- 关于BFC不会被浮动元素遮盖的一些解释
- MyBatis + MySQL返回插入成功后的主键id
- struts2+spring+hibernate整合步骤(1)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用 fyne 编写一个计算器程序
- Go 每日一库之 negroni
- Go 每日一库之 cli
- Go 每日一库之 cron
- Go 每日一库之 mapstructure
- Go 每日一库之 jobrunner
- 在本地运行 fyne 官网
- Python-科学计算-pandas-12-df单列计算
- JDK15就要来了,你却还不知道JDK8的新特性!
- 八佰:用Python看知乎 vs 豆瓣的战斗
- 学习Python你必须了解的lenna小姐姐
- 10行python代码制作笑死人不偿命的倒放gif
- “Hello Node.js” 这一次是你没见过的写法
- 作为DBA,你不得不掌握的压测工具
- Mac之vim普通命令使用