编者注:本文主要参考了《Python核心编程(第二版)》  

以下都是参考资料后,我自己的理解,如有错误希望大家不吝赐教。

大家有没有遇到这样一种情况,对象赋值后,对其中一个变量进行修改,另外一个变量的值也改变了。比如:

person = ['name', ['saving', 100]]
hubby = person
wifey = person
hubby[0] = 'joe'
wifey[0] = 'jane'
print hubby, wifey
hubby[1][1] = 50
print hubby, wifey
>>>['jane', ['saving', 100]] ['jane', ['saving', 100]]
['jane', ['saving', 50]] ['jane', ['saving', 50]]

以上的对象赋值实际上是简单的对象引用。也就是说当你创建一个对象,然后把他赋给另一个变量的时候,python并没有拷贝这个对象,而是拷贝了这个对象的引用。可以看出,hubby,wifey只是拷贝了person的引用,且是对person变量名,即列表整体的引用。

person = ['name', ['saving', 100]]
hubby = person
wifey = person
print [id(x) for x in person,hubby,wifey]
print [id(x) for x in person]
print [id(x) for x in hubby]
print [id(x) for x in wifey]
>>>[58507784L, 46008008L, 46008968L]
[37770104L, 58507336L]
[37770104L, 58507336L]
[37770104L, 58507336L]

可以看出,三个变量地址不一样,但三个变量的内容的地址一样,所以赋值后显示的结果一样。

常使用的浅拷贝类型有:
(1)完全切片操作[:]
(2)利用工厂函数list(),dict()等
(3)使用copy模块的copy函数

person = ['name', ['saving', 100]]
hubby = list(person)
wifey = person[:]
print [id(x) for x in person,hubby,wifey]
print [id(x) for x in person]
print [id(x) for x in hubby]
print [id(x) for x in wifey]
hubby[0] = 'joe'
wifey[0] = 'jane'
print hubby, wifey
hubby[1][1] = 50
print hubby, wifey
>>>[56541704L, 45680328L, 56541640L]
[37573496L, 56541256L]
[37573496L, 56541256L]
[37573496L, 56541256L]
['joe', ['saving', 100]] ['jane', ['saving', 100]]
['joe', ['saving', 50]] ['jane', ['saving', 50]]

   为什么这种浅拷贝hubby,wifey的名字不一样呢?第二个列表中值一样呢?因为list()和完全切边操作[:]是将person里的每个内容赋值,是对序列的引用。且这两个列表中第一个对象(字符串类型)是不可变的,第二个对象(一个列表)是可变的。正因如此,当进行浅拷贝时,字符串被显示的拷贝,并创建了一个字符串对象。而列表元素只是把它的引用复制了一下,并不是它的成员。

注意:
第一,非容器类型(比如数字,字符串,和其他‘原子’类型的对象,像xrange等)没有拷贝一说,浅拷贝是用完全切片操作完成的。第二,如果元组变量只包含原子类型对象,它的深拷贝将不会进行,只能得到一个浅拷贝。

import copy
person = ['name', ('saving', 100)]
hubby = person
wifey = copy.deepcopy(person)
print [id(x) for x in person,hubby,wifey]
print [id(x) for x in person]
print [id(x) for x in hubby]
print [id(x) for x in wifey]
>>>[56902216L, 56902216L, 56902152L]
[42095480L, 44124104L]
[42095480L, 44124104L]
[42095480L, 44124104L]

  

Python中的浅拷贝与深拷贝的更多相关文章

  1. python中的浅拷贝,深拷贝

    直接引用,间接引用 # 1.列表存储的是索引对应值的内存地址,值会单独的开辟一个内存空间 list = ["a","b"] 内存里面存储的就是list[0],l ...

  2. python中的浅拷贝和深拷贝

    1.赋值语句 a = 'abc' b = a print id(a) print id(b) # id(a):29283464 # id(b):29283464 通过简单的复制,我们可以看到,a b其 ...

  3. 16.python中的浅拷贝和深拷贝

    在讲什么是深浅拷贝之前,我们先来看这样一个现象: a = ['scolia', 123, [], ] b = a[:] b[2].append(666) print a print b

  4. (转+原)python中的浅拷贝和深拷贝

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6069722.html 原网址: http://blog.csdn.net/sunshine_in_mo ...

  5. Python 中的浅拷贝和深拷贝

    1. 列表和字典,直接赋值,都是浅拷贝,即赋值双方指向同一地址,因为 Python 对可变对象按引用传递. >>> a = [1, 2, 3] >>> b = a ...

  6. Python中的赋值、深拷贝与浅拷贝(内存地址)

    Python中的赋值.深拷贝与浅拷贝(内存地址) 1.python中的可变对象与不可变对象 (1) 可变对象:dict,list def dict_test(): a = {} b = a print ...

  7. 【转】JAVA中的浅拷贝和深拷贝

    原文网址:http://blog.bd17kaka.net/blog/2013/06/25/java-deep-copy/ JAVA中的浅拷贝和深拷贝(shallow copy and deep co ...

  8. python中的浅拷贝与赋值不同

    Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块. 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deep ...

  9. Python 引用、浅拷贝、深拷贝解析

    引用 Python是动态数据类型的语言,故在对变量进行赋值时是不用制定变量类型的. 或者说,你可以把变量赋值的过程,当作是贴一个标签,去引用该数据. 看下面的例子: In [54]: a=4 In [ ...

随机推荐

  1. Dockerfile中CMD和ENTRYPOINT的区别

    当启动一个容器时,CMD和ENTRYPOINT都可以用来执行启动命令.但它们的具体用法还是有一些区别: 1. Dockerfile必须至少指定CMD或者ENTRYPOINT其中的一个. 2. ENTR ...

  2. 基础二 day4 日记

    1.list增删改查 l1 = [1,'alex',True,[1,2,3],(2,3,4),{'name':'alex'}]l1 = ['alex',True,'wusir','ritian','t ...

  3. SQL Server 使用问题解答(持续更新中)

    问题一:sql server 2014不允许保存更改,您所做的更改要求删除并重新创建以下表 解答:工具-选项-不勾选组织保存要求重新创建表的更改,如下图确定.

  4. SQL的各种连接(cross join、inner join、full join)的用法理解

    SQL中的连接可以分为内连接,外连接,以及交叉连接 . 1. 交叉连接CROSS JOIN 如果不带WHERE条件子句,它将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积: 举例, ...

  5. 微信公众号tp3.2放进Model无效,几种实例化的方法试过,还是提示无法提供服务

    http://www.imooc.com/video/10230 解决方案一: $indexModel = D('Index');  实测可行 解决方案一: 使用TP3.2的小伙伴需要注意了,在Mod ...

  6. ThinkPhp5.0_文件上传

    ===================================================================== 路径: F:\wamp\www\public\uploads ...

  7. 可变数目参数----关键字params的使用

    如何定义和使用可变数目参数的方法,使用关键字params. 即其他语言的可变参数 Code public class App { static void Main() { //常规使用方法 Conso ...

  8. asp.net -mvc框架复习(5)-ASP.NET MVC中的视图简单使用

    1.视图分类 ASPX视图(现在讲解) Razor视图(后面讲解) ASPX 视图: 2.@page指令 作用:页面的声明 要求:必须放在第一行,常用指令属性如下: 3.服务器端内嵌语法 小脚本:在A ...

  9. JXLS使用方法(文件上传读取)xlsx文件读取

    1.官方文档:http://jxls.sourceforge.net/reference/reader.html 2.demo git地址:https://bitbucket.org/leonate/ ...

  10. Spring-AOP标签scoped-proxy

    <aop:scoped-proxy/>介绍: Spring的Bean是有scope属性的,表示bean的生存周期.scope的值有prototype.singleton.session.r ...