赋值、浅拷贝和深拷贝。

重点知识

浅拷贝和深拷贝的判断依据:新对象中元素与原对象中元素是否有关联

 

参考博客:http://blog.csdn.net/yugongpeng_blog/article/details/46604439

首先来看看浅拷贝和深拷贝的定义的不同。

浅拷贝:创建一个新的对象,其元素是对原对象元素的引用。

深拷贝:创建一个新的对象,然后递归拷贝原对象所包含的子对象。深拷贝出来的对象和元对象没有关联。

深拷贝和浅拷贝的区别仅仅是对组合对象来所。所谓的组合对象就是包含了其它对象的对象,例如列表、元祖等数据容器。

对于非容器类型(例如:字符串、数字和其他原子类型)来说,没有拷贝一说,产生的对象都是对原对象的应用。

在python中我们遇到的大部分拷贝,都是浅拷贝。

 

浅拷贝:切片操作、工厂函数、对象的copy方法、模块中的copy函数。

深拷贝:只有一种,copy模块中的deepcopy函数。

 

从定义来看已经能非常好的区分拷贝的种类。

深拷贝和浅拷贝都创建了一个新的对象,所以深拷贝和浅拷贝创建的对象的内存地址与原对象的内存地址肯定是不同的,这不足以成为判断的依据。

区别在于新对象中的元素与原对象中的元素是否存在联系。如果有联系则属于浅拷贝,否则属于深拷贝。

 

首先,来看看浅拷贝

>>> ssw ='bangzi'
>>> ssb =list(ssw)  #ssb是通过工厂函数浅拷贝过来的一个新的对象
>>> ssw
'bangzi'
>>> ssb
['b', 'a', 'n', 'g', 'z', 'i']  

>>> id(ssw),id(ssb)
(139798160206232, 139798160220040)  #两个对象的内存地址不一样


>>> for x,y in zip(ssw,ssb):    #针对于对象中的元素来说,两个对象中的每个元素指向的都是一个元对象。
...     print(id(x),id(y))
... 
139798160566736 139798160566736
139798160335792 139798160335792
139798160718736 139798160718736
139798160372040 139798160372040
139798160206512 139798160206512
139798160567856 139798160567856

再来看几个其他浅拷贝的例子:

通过工厂函数所得到的对象
>>> YY1 = [1,2,3,4,5,6]
>>> YY2 =tuple(YY1)    #序列变元祖
>>> YY2
(1, 2, 3, 4, 5, 6)
>>> id(YY1),id(YY2)
(139798032994568, 139798159622216)
>>> for x,y in zip(YY1,YY2):
...     print(id(x),id(y))
... 
9323200 9323200   #对象中的元素与原对象中的元素id号一致。
9323232 9323232
9323264 9323264
9323296 9323296
9323328 9323328
9323360 9323360

工厂函数有:list()、tuple()、dict()、str()。

通过切片操作得到的对象
>>> a = [1,2,3,4,5]
>>> b = a[:3]
>>> id(a)
139798160216200
>>> id(b)
139798160218760

>>> id(b[0])      #对原对象元素的引用。
9323200
>>> id(a[0])
9323200
>>> id(b[1])
9323232
>>> id(a[1])
9323232

 

通过copy函数得到的对象也是浅拷贝
>>> info = {'name':'kebi','age':'28'}
>>> INFO = info.copy()
>>> INFO
{'name': 'kebi', 'age': '28'}

>>> id(info)    #内存地址虽然不同
139798160737480
>>> id(INFO)
139798160195448

>>> id(info['name'])   #元素都指向一个地方,明显的浅拷贝。
139798160206456
>>> id(INFO['name'])
139798160206456

 

其次,是深拷贝。

>>> a = [[1,2],[3,4],[5,6]]
>>> c = copy.deepcopy(a)
>>> id(a),id(c)
(139798032994376, 139798032994504)   #对象的内存地址不一样
>>> for x,y in zip(a,c):
...     print(id(x),id(y))
... 
139798160216200 139798032882312  #对象中每个元素并不是对原对象中元素的引用,二者之间没有关联。
139798032994440 139798032882376
139798032883656 139798032883592

 

最后,说说赋值。

什么是变量?

将某一数值赋给某个变量的过程,称为赋值。

>>> id(s)   #没有赋值,s没有任何意义。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 's' is not define

>>> s = 1#给s赋值
>>> id(s)
9323200

用一个变量给另一个变量赋值,其实就是给当前内存空间中的对象增加了一个标签。

>>> y = 1
>>> id(y)
9323200
>>> h = s
>>> id(h)
9323200

 改变其中一个值,另一个值也会随之改变。

>>> l1 = [1,2,3,4]
>>> l2 = l1
>>> l1.append(6)
>>> l1
[1, 2, 3, 4, 6]
>>> l2
[1, 2, 3, 4, 6]

 

posted @ 2017-10-27 16:18  明王不动心  阅读(290)  评论(0编辑  收藏  举报