鱼C论坛

 找回密码
 立即注册
查看: 1763|回复: 2

[已解决]关于 拷贝 和 赋值

[复制链接]
发表于 2017-4-2 17:11:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
小甲鱼在讲解12章节的时候,直接用list1=list2 ,会使得list1的元素会存在随着list2改变而改变的风险,但是为什么普通的变量不会呢?
  1. >>> x=3;
  2. >>> y=x;
  3. >>> y
  4. 3
  5. >>> x=5
  6. >>> y
  7. 3
  8. >>> x
  9. 5
  10. >>> list1=[1,2,3]
  11. >>> list2 =list1
  12. >>> list1.sort(reverse=True)
  13. >>> list2
  14. [3, 2, 1]
复制代码
最佳答案
2017-4-2 17:29:09
大家都知道,在python中复制一个对象有多种方法,其中常用的是赋值、浅拷贝和深拷贝,这三者之间有哪些区别和哪些坑呢?

首先,定义一下:

  赋值:  a =1    b =a    a赋值给了b

  浅拷贝: a = []          b = a.copy()

      或者import copy             b = copy.copy(a)

  深拷贝:import copy   a = []   b = copy.deepcopy(a)

通常,我们使用id()方法来查看对象的内存地址。

python对不同类型对象所采取的策略是不一样的,所以我们必须区分不同的类型来进行分析:

(以下全部在python3.5.1环境中测试)

一、数字型

View Code
  从测试中我们可以看出,对于数字类型,不管是赋值还是深浅拷贝,一律都是指向同一块地址,而一旦a的值改变了则a重新指向新的内存空间,a,b,c,d成为完全独立的4个变量。一句话概括,对于数据类型随便怎么赋值拷贝,所有变量不会互相影响。(注意,数字类型没有copy()方法。)

二、字符串

字符串
  从测试中我们可以看出,字符串类型和数字类型一样,不管是赋值还是深浅拷贝,一律都是指向同一块地址,而一旦a的值改变了则a重新指向新的内存空间地址。一句话概括,对于字符串类型随便怎么赋值拷贝,所有变量不会互相影响。(注意,字符串类型同样没有copy()方法。)

字符串的切片赋值
  同样的,字符串的切片赋值和上面也是一样的效果。

三、列表

赋值
  可见,对于列表,赋值其实也是将新的变量指向同样的地址,a的变化会影响到b,b就相当于a的一个符号链接,两者基本等同。

列表的copy()方法
  对于列表的copy()方法,从一开始,b就有了和a不同的内存地址,因此对于a的最顶层次的元素的修改,影响不到b。但是!下一层次的修改却在b中得到了反映。这说明copy()方法是一个浅拷贝。

copy模块的copy()方法
  从例子中可以看出,copy模块的copy()方法可上面的copy方法一样,都是浅拷贝。

deepcopy()方法
  从例子中可以看出,copy模块的deepcopy()方法可以实现深层次的复制,达到完整复制出一份互不干扰的拷贝

切片方法
  大家知道,字符串、元组和列表有一种切片复制的方法,即b = a[:]。从上面的代码中,我们可以发现,切片其实也是一种浅拷贝。(注意:字典没有切片功能)

四、字典

赋值
  从例子中可以见到,赋值的时候,两个字典指向同一个地址,b就是a的一个软链接,相当于别名。

copy方法
  从例子中可以看到,字典的copy方法开辟了一块新的内存空间,但是这也是浅拷贝,只有最顶层的元素获得了独立,以下层次的元素依然指向同一个地址。

copy模块的copy方法
  从例子看出,和上面的一样,这也是个浅拷贝。



deepcopy方法
  从例子中可以看出,deepcopy方法完全复制了一份独立的拷贝。

总结:

1.对于数值和字符串类型,属于轻量级对象,python采用的是‘硬’拷贝的方法,每个变量都成为独立的个体。

2.对于列表和字典,为了节省内存空间,python通常采用浅拷贝的方法,只对最顶层的元素进行复制,而以下层次的内容依然指向同一块地址。只有采用深拷贝的方法才能复制出一份独立的拷贝。列表和字典基本是一样的策略,除了字典没有切片功能。

3.浅拷贝只复制列表和字典的最顶层的元素,对于下级的元素依然指向同样的地址,也就是说有关联性。而深拷贝则是完全复制了一份独立的拷贝。



五、使用建议

1. 对于数值、字符串,直接赋值就好,每一个变量都是独立的个体,不用考虑深浅拷贝的问题。

2.对于列表和字典,如果你想完全复制那么只能用deepcopy()方法;如果浅拷贝就行,那可以用copy()方法。但是,不要赋值,因为这实际没什么意义,只是给变量取了个别名而已。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-4-2 17:29:09 | 显示全部楼层    本楼为最佳答案   
大家都知道,在python中复制一个对象有多种方法,其中常用的是赋值、浅拷贝和深拷贝,这三者之间有哪些区别和哪些坑呢?

首先,定义一下:

  赋值:  a =1    b =a    a赋值给了b

  浅拷贝: a = []          b = a.copy()

      或者import copy             b = copy.copy(a)

  深拷贝:import copy   a = []   b = copy.deepcopy(a)

通常,我们使用id()方法来查看对象的内存地址。

python对不同类型对象所采取的策略是不一样的,所以我们必须区分不同的类型来进行分析:

(以下全部在python3.5.1环境中测试)

一、数字型

View Code
  从测试中我们可以看出,对于数字类型,不管是赋值还是深浅拷贝,一律都是指向同一块地址,而一旦a的值改变了则a重新指向新的内存空间,a,b,c,d成为完全独立的4个变量。一句话概括,对于数据类型随便怎么赋值拷贝,所有变量不会互相影响。(注意,数字类型没有copy()方法。)

二、字符串

字符串
  从测试中我们可以看出,字符串类型和数字类型一样,不管是赋值还是深浅拷贝,一律都是指向同一块地址,而一旦a的值改变了则a重新指向新的内存空间地址。一句话概括,对于字符串类型随便怎么赋值拷贝,所有变量不会互相影响。(注意,字符串类型同样没有copy()方法。)

字符串的切片赋值
  同样的,字符串的切片赋值和上面也是一样的效果。

三、列表

赋值
  可见,对于列表,赋值其实也是将新的变量指向同样的地址,a的变化会影响到b,b就相当于a的一个符号链接,两者基本等同。

列表的copy()方法
  对于列表的copy()方法,从一开始,b就有了和a不同的内存地址,因此对于a的最顶层次的元素的修改,影响不到b。但是!下一层次的修改却在b中得到了反映。这说明copy()方法是一个浅拷贝。

copy模块的copy()方法
  从例子中可以看出,copy模块的copy()方法可上面的copy方法一样,都是浅拷贝。

deepcopy()方法
  从例子中可以看出,copy模块的deepcopy()方法可以实现深层次的复制,达到完整复制出一份互不干扰的拷贝

切片方法
  大家知道,字符串、元组和列表有一种切片复制的方法,即b = a[:]。从上面的代码中,我们可以发现,切片其实也是一种浅拷贝。(注意:字典没有切片功能)

四、字典

赋值
  从例子中可以见到,赋值的时候,两个字典指向同一个地址,b就是a的一个软链接,相当于别名。

copy方法
  从例子中可以看到,字典的copy方法开辟了一块新的内存空间,但是这也是浅拷贝,只有最顶层的元素获得了独立,以下层次的元素依然指向同一个地址。

copy模块的copy方法
  从例子看出,和上面的一样,这也是个浅拷贝。



deepcopy方法
  从例子中可以看出,deepcopy方法完全复制了一份独立的拷贝。

总结:

1.对于数值和字符串类型,属于轻量级对象,python采用的是‘硬’拷贝的方法,每个变量都成为独立的个体。

2.对于列表和字典,为了节省内存空间,python通常采用浅拷贝的方法,只对最顶层的元素进行复制,而以下层次的内容依然指向同一块地址。只有采用深拷贝的方法才能复制出一份独立的拷贝。列表和字典基本是一样的策略,除了字典没有切片功能。

3.浅拷贝只复制列表和字典的最顶层的元素,对于下级的元素依然指向同样的地址,也就是说有关联性。而深拷贝则是完全复制了一份独立的拷贝。



五、使用建议

1. 对于数值、字符串,直接赋值就好,每一个变量都是独立的个体,不用考虑深浅拷贝的问题。

2.对于列表和字典,如果你想完全复制那么只能用deepcopy()方法;如果浅拷贝就行,那可以用copy()方法。但是,不要赋值,因为这实际没什么意义,只是给变量取了个别名而已。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-4-2 19:36:04 | 显示全部楼层
新手·ing 发表于 2017-4-2 17:29
大家都知道,在python中复制一个对象有多种方法,其中常用的是赋值、浅拷贝和深拷贝,这三者之间有哪些区别 ...

好具体呀,非常感谢版主,给你fafa~(づ ̄ 3 ̄)づ
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 07:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表