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,实现了真正的隔离。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP在线

php面试题(一)

1 <?php echo -10%3; ?> 答案:-1。 考查:优先级。 因为-的优先级比%求余的优先级低,也就是-(10%3)。 2 print (int...

3717
来自专栏coding for love

JS入门难点解析9-闭包的深入解析

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

652
来自专栏一名合格java开发的自我修养

java或判断优化小技巧

写业务代码的时候,我们经常要做条件判断,有的时候条件判断的或判断长达20多个。reg.equals("1") || reg.equals("2") || reg...

621
来自专栏Crossin的编程教室

【Python 第52课】 元组

上一次pygame的课中有这样一行代码: x, y = pygame.mouse.get_pos() 这个函数返回的其实是一个“元组”,今天我们来讲讲这个东西。...

3387
来自专栏Python入门

十年Python大牛花了三天总结出来的python基础知识实例,超详细!

6、变量在内存中是通过引用计数来跟踪管理的~想要一起学习Python的可以加裙227-435-450,裙内有各种资料满足大家,欢迎加裙

3481
来自专栏编程

Python入门基础连载(2)数据结构

Python数据结构包括了列表(list),元组(tuple),字典(dict)和集合(set),这些也都可以称之为容器,下面Cooldog就和大家一起学习一下...

2037
来自专栏大数据钻研

让你分分钟学会 javascript 闭包

闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它。...

2764
来自专栏企鹅号快讯

Python入门基础连载(1)数据类型

Python入门很简单,应该说语法还是很简单明了,有一定C或者java或者别的语言基础的亲们都能明白。大数据,机器学习大势所趋,乘着这风,大家一起学习Pytho...

1996
来自专栏python学习之旅

Python笔记(七):字典、类、属性、对象实例、继承

(一)  简单说明    字典是Python的内置数据结构,将数据与键关联(例如:姓名:张三,姓名是键,张三就是数据)。例如:下面这个就是一个字典 {'姓名':...

3835
来自专栏zhisheng

干货分享:让你分分钟学会 javascript 闭包 一像素

闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它。...

3485

扫码关注云+社区

领取腾讯云代金券