我们在很多方法里都看到copy()方法,这是对变量的复制,赋值,下面来看一下实例:

复制方法调用的是copy模块中的方法:

import copy

  copy.copy()         #前拷贝

  copy.deepcopy()     #深拷贝

我们可以让一个变量等于另一个变量可以采用赋值的方式,比如a = b等,让变量a = b变量,还可以通过copy()来实现。下面来看看在各种情况下的关联情况:

    一、字符串和数字的情况

>>> import copy
  >>> a = 3
  >>> b = a
  >>> c = copy.copy(a)
  >>> d = copy.deepcopy(a)
  >>> b
  3
  >>> c
  3
  >>> d
  3
    >>> print(id(a),id(b),id(c),id(d))
  10914432 10914432 10914432 10914432
    从上面可以看出,我们通过导入模块copy,这个模块专门用于复制,可以看到在数字中,采用赋值、copy()、deepcopy()三种方式,我们发现采用三种方式的方式,都是把地址关联过去,具有相同的地址,说明是采用如下方式进行管理的。实例如下:

从上图可以看出,在数字和字符串中,三种任意方式都是关联到字符串或数字所在的内存,是把内容关联过去,因此无论采用那种方式都是一样的

。下面来看一看在列表,元组、字符串、字典中的情况。

二、列表,元组,字典一层复制情况

列表、字典的情况

    1、在列表中的情况

import copy
  l = ["alex",11,"sb","tom"]
  d = {"k1":"v1","k2":22,"k3":"alex"}
  t = (11,'ALEX',"sb")

  l1 = l
  l2 = copy.copy(l)
  l3 = copy.deepcopy(l)

  print(id(l),id(l1),id(l2),id(l3))

  #下面来修改一下列表中的元素,看看关联情况编程什么样了,如下:
  l.append("Aoi")
  print(l,l1,l2,l3)
  print(id(l),id(l1),id(l2),id(l3))
    2、在字典中的情况
  d1 = d
  d2 = copy.copy(d)
  d3 = copy.deepcopy(d)
  print(id(d),id(d1),id(d2),id(d3))
  d.__setitem__("tom","Hello")
  print(d,"\n",d1,"\n",d2,"\n",d3)
  print(id(d),id(d1),id(d2),id(d3))

  运行结果如下:

    列表中的运算结果:

140006457636360 140006457636360 140006457672456 140006457637320
  ['alex', 11, 'sb', 'tom', 'Aoi'] ['alex', 11, 'sb', 'tom', 'Aoi'] ['alex', 11, 'sb', 'tom'] ['alex', 11, 'sb', 'tom']
  140006457636360 140006457636360 140006457672456 140006457637320
  140006482186568 140006482186568 140006457674440 140006457636680
  字典中的运算结果:

{'k2': 22, 'k3': 'alex', 'tom': 'Hello', 'k1': 'v1'}
  {'k2': 22, 'k3': 'alex', 'tom': 'Hello', 'k1': 'v1'}
   {'k2': 22, 'k1': 'v1', 'k3': 'alex'}
  {'k2': 22, 'k1': 'v1', 'k3': 'alex'}
  140006482186568 140006482186568 140006457674440 140006457636680

可以看出,在列表中我们通过等号赋值(=)、copy(list)、deepcopy(list)方法打印变量的ip地址,可以看出,等号赋值(=)与原来变量的地址是一样的,因此等号的赋值方式是这样的:

等号赋值无论在关联字典还是列表的过程中,都是指向同一个Python开辟的内存地址,a和b的内存地址永远是一致的,只要a发生了变化,相应的b就发生变化。

而在字典中copy()和deepcopy()确是下面的形式:

为什么我猜测copy()是上面的形式呢,我们来看一段代码:

import copy
  l = ["alex",11,"sb","tom"]
  d = {"k1":"v1","k2":22,"k3":"alex"}                                   (1)
  t = (11,'ALEX',"sb")

  l1 = l
  l2 = copy.copy(l)
  l3 = copy.deepcopy(l)

  print(id(l),id(l1),id(l2),id(l3))

  #下面来修改一下列表中的元素,看看关联情况编程什么样了,如下:
  l.append("Aoi")
  print(l,l1,l2,l3)
  print(id(l),id(l1),id(l2),id(l3))

  d1 = d
  d2 = copy.copy(d)                                        (2)
  d3 = copy.deepcopy(d)
  print(id(d),id(d1),id(d2),id(d3))                        (3)
  d.__setitem__("tom","Hello")
  print(d,"\n",d1,"\n",d2,"\n",d3)
  print(id(d),id(d1),id(d2),id(d3))                         (4)

  del d["k1"]                                               (5)
  print(d,"\n",d1,"\n",d2,"\n",d3)
  print(id(d),id(d1),id(d2),id(d3))                          (6)

代码运行如下:

140353118074376 140353118074376 140353118110472 140353118074760
  ['alex', 11, 'sb', 'tom', 'Aoi'] ['alex', 11, 'sb', 'tom', 'Aoi'] ['alex', 11, 'sb', 'tom'] ['alex', 11, 'sb', 'tom']
  140353118074376 140353118074376 140353118110472 140353118074760
  140353142624584 140353142624584 140353118112456 140353118075272
  {'k1': 'v1', 'tom': 'Hello', 'k2': 22, 'k3': 'alex'}
   {'k1': 'v1', 'tom': 'Hello', 'k2': 22, 'k3': 'alex'}
   {'k1': 'v1', 'k2': 22, 'k3': 'alex'}
   {'k1': 'v1', 'k2': 22, 'k3': 'alex'}
  140353142624584 140353142624584 140353118112456 140353118075272
  {'tom': 'Hello', 'k2': 22, 'k3': 'alex'}
   {'tom': 'Hello', 'k2': 22, 'k3': 'alex'}
   {'k1': 'v1', 'k2': 22, 'k3': 'alex'}
   {'k1': 'v1', 'k2': 22, 'k3': 'alex'}
  140353142624584 140353142624584 140353118112456 140353118075272

在上面(1)处我们定义了一个字典,在(2)处我们使用copy.copy()产生一个新的变量d2,然后我们打印变量d、d2的id(d)、id(d2),我们可以看出,两者的id()是不一样的,因此可以说明在系统中是存在了两个位置存放d和d2的,而不是一个位置,仅凭这一点还不足以说明,下面来看(5)处,我们删除了字典d中的键-值对"k1",此时如果两者存在关联的话,那么d2中键-值对"k1":"v1"必然也会被删除,事实上并没有,而且我们修改元素的时候,如果它们之间存在指向关系的话,那么copy()也会让d2中的添加一个键-值对"tom":"Hell0"。事实上并没有,所以我断定,无论怎样使用copy()方法都是在内存中新开辟了一个地址,如果只有一层的话,这两个地址之间也是没有关联的。

如果字典只有一层,那么使用deepcopy()方法也是一样的,图例如下:

三、列表,元组,字典多层情况的赋值情况

上面我们研究了copy()、deepcopy()单层的情况,下面来看看多层的情况,首先定义一个字典n1={"k1":123,"k2":"wupie","k3":[123,"alex"]}

,

在python中,copy()、deepcopy()的设置挺复杂的,相同元素的id是一样的,但是在删除的时候又不会影响由copy()、deepcopy()产生的变量,

但是在使用copy()的时候,第二层的元素还是与原来的元素关联在一起,下面来看一个例子:

import copy

  n1 = {"k1":123,"k2":"wupie","k3":[456,"alex"]}

  #打印k1的ip地址
  n2 = copy.copy(n1)
  n3 = copy.deepcopy(n1)

  print(n1,"\n" ,n2,"\n",n3)
  print(id(n1),id(n2),id(n3))
  print(id(n1["k1"]),id(n2["k1"]),id(n3["k1"]),"\n")

  #打印k2的地址
  print(id(n1["k2"]),id(n2["k2"]),id(n3["k2"]),"\n")

  #打印"k3"的ip地址
  print(id(n1["k3"]),id(n2["k3"]),id(n3["k3"]),"\n")

  #修改“k1"的值
  n1["k1"] = 888

  #打印修改后的信息
  print(n1,"\n" ,n2,"\n",n3)
  print(id(n1),id(n2),id(n3))
  print(id(n1["k1"]),id(n2["k1"]),id(n3["k1"]),"\n")

  #打印修改后的k2的地址
  print(id(n1["k2"]),id(n2["k2"]),id(n3["k2"]),"\n")

  #打印"k3"的ip地址
  print(id(n1["k3"]),id(n2["k3"]),id(n3["k3"]),"\n")

  #修改"k3"中的值
  n1["k3"][0] = 666
  print(n1,"\n" ,n2,"\n",n3)
  print(id(n1),id(n2),id(n3))
  print(id(n1["k1"]),id(n2["k1"]),id(n3["k1"]),"\n")

  #打印修改后的k2的地址
  print(id(n1["k2"]),id(n2["k2"]),id(n3["k2"]),"\n")

  #打印"k3"的ip地址
  print(id(n1["k3"]),id(n2["k3"]),id(n3["k3"]),"\n")

  #删除"k3"的键值对
  del n1["k3"]
  print(n1,"\n" ,n2,"\n",n3)
  print(id(n1),id(n2),id(n3))print(id(n1["k1"]),id(n2["k1"]),id(n3["k1"]),"\n")

  #打印修改后的k2的地址

  print(id(n1["k2"]),id(n2["k2"]),id(n3["k2"]),"\n")

  try:#打印"k3"的ip地址

    print(id(n1["k3"]),id(n2["k3"]),id(n3["k3"]),"\n")

  except KeyError:

     print(id(n2["k3"]),id(n3["k3"]))id(n2),id(n3))print(id(n1["k1"]),id(n2["k1"]),id(n3["k1"]),"\n")#打印修改后的k2的地址print(id(n1["k2"]),id(n2["k2"]),id(n3["k2"]),"\n")try:#打印"k3"的ip地址 print(id(n1["k3"]),id(n2["k3"]),id(n3["k3"]),"\n")except KeyError: print(id(n2["k3"]),id(n3["k3"]))

运行结果如下:

10918272 10918272

  139928163731640 139928163731640 139928163731640

  139928139736520 139928139736520 139928139737608

  {'k3': [666, 'alex'], 'k1': 888, 'k2': 'wupie'}
   {'k3': [666, 'alex'], 'k1': 123, 'k2': 'wupie'}
   {'k3': [456, 'alex'], 'k1': 123, 'k2': 'wupie'}
  139928164286856 139928139772744 139928139736968
  139928164089648 10918272 10918272

  139928163731640 139928163731640 139928163731640

  139928139736520 139928139736520 139928139737608

  {'k1': 888, 'k2': 'wupie'}
   {'k3': [666, 'alex'], 'k1': 123, 'k2': 'wupie'}
   {'k3': [456, 'alex'], 'k1': 123, 'k2': 'wupie'}
  139928164286856 139928139772744 139928139736968
  139928164089648 10918272 10918272

  139928163731640 139928163731640 139928163731640

  139928139736520 139928139737608

在上面例子中,我们首先定义了一个变量n1,里面嵌套了一层字典,然后使用copy(),deepcopy()生成了新的变量n2,n3并且打印了n1,n2,n3的ip地址,由ip地址可以看出,n1,n2,n3是在内存中有不同的存储位置的,接着我们打印了键-值对“k1”的存储id,结果发现,三者的“k1”存储的id位置是一样的,说明还是用的原来位置的id,这样节省了内存,接着我们看“k3”的ip地址,可以看出,使用copy()得到的ip地址与n1的“k3”的id是一样的,说明是用的一个id,我们修改字典n1中的元素"k3"之后,n2也跟着变化,说明字典n1中的“k3”和字典n2中的“k3”存在某种管理,但是当我们删除字典n1中的“k3”之后,字典n2中的"k3"不受影响,还存在,说明使用copy()生成的变量,第二层关联之间存在着某种关联,但是又不完全依存,第一层之间共用一个地址,节省了内存,但是在原来的字典发生变化的时候又不影响之前的变量,只是对新的变量开辟了一个空间,用来存放位置。

有一个监控模板,包含内存,硬盘,有一批机器,现在是按dic模式运行的,现在要修改其中一部分的及其的硬盘,其他部分不改变。

import copy
  dic = {
  "cpu":[80,],
  "men":[80,],
  "disk":[80]
  }

  print("before:",dic)
  new_dic = copy.deepcopy(dic)
  new_dic["cpu"][0] = 50

  print(dic,"\n",new_dic)

在上面,我们使用copy模块的deepcopy来进行处理,我们知道,有很多信息,在嵌套中,只有deepcopy()才会生成第二层的信息。

copy深浅拷贝的更多相关文章

  1. 包,logging日志模块,copy深浅拷贝

    一 包 package 包就是一个包含了 __init__.py文件的文件夹 包是模块的一种表现形式,包即模块 首次导入包: 先创建一个执行文件的名称空间 1.创建包下面的__init__.py文件的 ...

  2. Python:深浅拷贝

    导入模块: >>> import copy 深浅拷贝: >>> X = copy.copy(Y) #浅拷贝:只拷贝顶级的对象,或者说:父级对象 >>&g ...

  3. @proprety数组字典字符串用copy和strong区别(深浅拷贝)

    ////  @proprety数组字典字符串用copy和strong区别(深浅拷贝).h//  IOS笔记//// /* _proprety________copy_strong_________h ...

  4. 关于:1.指针与对象;2.深浅拷贝(复制);3.可变与不可变对象;4.copy与mutableCopy的一些理解

    最近对深浅拷贝(复制)做了一些研究,在此将自己的理解写下来,希望对大家有所帮助.本人尚处在摸索阶段,希望各位予以指正. 本文包括如下方向的探索: 1.指针与对象: 2.深/浅拷贝(复制): 3.可变/ ...

  5. copy之深浅拷贝

    深浅拷贝深拷贝 全部复制浅拷贝 只复制第一层 __author__ = 'Perfect' # -*- coding: utf-8 -*- import copy # copy.copy() #浅拷贝 ...

  6. 深浅拷贝的应用-copy、mutableCopy

    ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController //如果想让li ...

  7. 深浅拷贝(copy)

    目录 copy 模块 1.拷贝(赋值) 1). x为不可变数据类型 2). x为可变数据类型 3). 可变数据类型(比如列表)内,既有不可变元素,又有容器类型可变元素(比如列表) 2.浅拷贝 3.深拷 ...

  8. Python 从零学起(纯基础) 笔记 之 深浅拷贝

    深浅拷贝 1. import  copy#浅拷贝copy.copy()#深拷贝copy.deepcopy()#赋值 = 2.   对于数字和字符串而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个 ...

  9. python——赋值与深浅拷贝

    初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从内存的角度来谈一谈赋值和深浅拷贝~~~ 预备知识一——python的变量及其存储 在详细的了解python中赋 ...

随机推荐

  1. Codeforces Round #417 (Div. 2)A B C E 模拟 枚举 二分 阶梯博弈

    A. Sagheer and Crossroads time limit per test 1 second memory limit per test 256 megabytes input sta ...

  2. BNU-2017.7.4排位赛2总结

    链接:https://www.bnuoj.com/v3/contest_show.php?cid=9147#info A题 sort之后交换首尾两个数. B题 for一遍,如果每个数都在对应位置了,输 ...

  3. Codeforces 833B The Bakery dp线段树

    B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  4. css中px em rem vw vh vmax vmin等单位的区别--转载

    px:绝对单位,页面按精确像素展示 em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值. rem:相对 ...

  5. 在Centos系统下使用命令安装gnome图形界面程序

    第一步:先检查yum 是否安装了,以及网络是否有网络.如果这两者都没有,先解决网络,在解决yum的安装. 第二步:在命令行下 输入下面的命令来安装Gnome包. # yum groupinstall ...

  6. UVA 1650 Number String

    https://vjudge.net/problem/UVA-1650 题意:D表示比前一个数打,I表示比前一个数小,?表示不确定 给出一个长为n由D I?组成的字符串,问满足字符串大小要求的n+1的 ...

  7. 超越icon font

    很久以前,我们如何使用图标? 1.切图 2.拼合(Sprites) 原始社会啊! 后来CSSGagagrunt-css-sprite 字体图标 相见不曾相识 Emoji绘文字 iconfont.cn直 ...

  8. Oracle Number类型超长小数位为0问题

    碰到了一个非常奇怪的问题,从Excel拷贝出来的数据,位数很长,通过Pl Sql 导出到Oracle后为0了,而且设置查询条件为0时,无法查询出来,条件大于0居然能查询出来,通过to_number也是 ...

  9. 【BZOJ】4596: [Shoi2016]黑暗前的幻想乡

    [题意]给定n个点的无向完全图,有n-1个公司各自分管一部分路,要求所有公司都有修路的生成树数.n<=17. [算法]容斥原理+生成树计数(矩阵树定理) [题解]每个生成树方案是一个公司有无修路 ...

  10. matlab前景分割

    用最简单的差分法实现了一下前景分割.使用的mall数据集. 思路是这样的:首先设定一个队列的长度,若读取的图片张数少于队列长度则以当前读取到的图片做平均.否则则以队列中的图片做平均. 这样之后和当前图 ...