编者注:本文主要参考了《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. UWP: 通过命令行启动 UWP 应用

    最近在开发应用的过程中,我遇到了如标题所述的需求,其实主要是为了能够快捷启动应用,正像我们可以在"运行"对话框中可以输入一些可执行程序的名称后,就能够直接启动它:这样做,可以增加 ...

  2. ngRx 官方示例分析 - 2. Action 管理

    我们从 Action 名称开始. 解决 Action 名称冲突问题 在 ngRx 中,不同的 Action 需要一个 Action Type 进行区分,一般来说,这个 Action Type 是一个字 ...

  3. 风险案例-28期-项目Leader与团队成员缺乏沟通,问题响应度较慢导致团队士气低落,工作效率低

    典型案例: A公司某C类项目目前进入开发高峰期,项目组的三个leader预计在项目的实际task投入占比为70%,剩30%工作时间用于指导组员进行作业实施并担当部分管理工作.从项目实施过程中发现Lea ...

  4. label+input实现开关切换效果

    Document 主要使用label+input来实现改变left的值,下面是核心代码,意思就是选中的input的兄弟节点.box下的.switch-btn元素的left会变成0px(原来是-37px ...

  5. python3 第十八章 - 迭代器与生成器

    1.迭代器(Iterator) 迭代是访问集合元素的一种方式 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 迭代器 ...

  6. JAVA中文件与Byte数组相互转换的方法

    JAVA中文件与Byte数组相互转换的方法,如下: public class FileUtil { //将文件转换成Byte数组 public static byte[] getBytesByFile ...

  7. test for python socket

    server: #!/usr/bin/python import socket import threading import time def tcplink(sock, addr): print ...

  8. 【转】 C++易混知识点4: 自己编写一个智能指针(Reference Counting)学习auto_ptr和reference counting

    这篇文章建大的介绍了如何编写一个智能指针. 介绍: 什么是智能指针?答案想必大家都知道,智能指针的目的就是更好的管理好内存和动态分配的资源,智能指针是一个智能的指针,顾名思义,他可以帮助我们管理内存. ...

  9. Gitlab备份与恢复[七]

    标签(linux): git 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 备份 配置文件中加入 gitlab_rails['bakup_path']='/da ...

  10. JQuery 纵向二级菜单与对齐方式

    1.效果: 2.代码: style部分: <style type="text/css"> /* ul{margin: 0; padding: 0;}*/ ul{list ...