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

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

>>> a = [1,2,3,4]
>>> b = [1,2,3,4]
>>> a == b
True
>>> a is b
False


  可以看见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 == b
True
>>> a is b
True
>>> 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]

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值