流畅的python--深拷贝,浅拷贝

来源:互联网 发布:2016年离婚率数据 编辑:程序博客网 时间:2024/05/18 02:37

说到python中的对象引用问题,还得看看is和==的区别:

>>> a = [1,2,3,4]>>> b = [1,2,3,4]>>> a == bTrue>>> a is bFalse


  可以看见a和b中的数值都是一样的,但是==与is的结果却不是一样的,这是因为python中==比较的是a和b的数值相等,is比较对象的标识是否相等。所以在python中我们经常会使用==来比较对象的数值时候相等, 判断对象绑定的值时候是None, 最好使用is。这里面有一个坑,一些新手经常犯的错误,空字符串,空列表,空字典,他们的都等于False,但是他们都不是(不等于)None,所以在判断一个字符串,列表,字典是否为空时, 不要用None来做比较,因为这些变量无论是从对象标识,数值都与None不相等。

  我们平常是用的对象复制一般都是浅拷贝。copy模块为我们提供了copy(浅拷贝),deepcopy(深拷贝)函数。

什么是浅拷贝:

  浅拷贝就是将拷贝的对象引用拷贝一份,拷贝对象指向的是被拷贝对象的数值,简单的说就是,在原有数值上面再添加的一份引用。

>>> a =1>>> b =a>>> id(a)4297636352>>> id(b)4297636352

什么是深拷贝:

  深拷贝就是拷贝对象对被拷贝对象数值上复制一份,然后新建一个对象,这个新的对象数值,对象标识都是和被拷贝对象相等的,

>>> import copy>>> a = [1,2,3]>>> b = copy.deepcopy(a)>>> b[1,2,3]>>> a[1,2,3]>>> a == bTrue>>> a is bTrue>>> id(a)4297636352>>> id(b)4297636352>>> a.append(0)>>> a[1,2,3,0]>>> b[1,2,3]>>> b.append(9)>>> b[1, 2, 3, 9]>>> a[1, 2, 3, 0]

  基于这种现象,所以我们应该特别注意函数在使用可变参数
  作为默认参数,如不注意就会出现下面这种情况:

>>> def a(x = []):...     x.append(0)...     print(x)... >>> a()[0]>>> a()[0, 0]>>> a()[0, 0, 0]

  为了避免这种情况我们应该避免使用可变对象作为函数默认参数:

>>> def a(x = None):...     if x is None:...             x = []...     else:...             x.append(0)...     print(x)... >>> a()[]>>> a()[]

同时创建类初始化传参也是使用浅拷贝来传递的,这样就会出现这种情况:

>>> class A:...     def __init__(self, name):...         self.name = name...     def printf(self):...         print(self.name)... >>> x = [1,2,3,4]>>> a = A(x)>>> a.printf()[1, 2, 3, 4]>>> x.append(5)>>> a.printf()[1, 2, 3, 4, 5]

在传入的参数改变的时候,类里面的变量的值页跟着改变了,这种情况时最懒发现的。