Chinaunix首页 | 论坛 | 博客
  • 博客访问: 104449
  • 博文数量: 67
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 577
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-16 09:51
个人简介

啄木鸟专吃虫,故名啄木鸟。

分类: Python/Ruby

2014-09-02 20:10:20

感觉这个例子十分的深入浅出,故mark一下。一家人存钱的典故
>>> person = ['name',['saving',100]]
>>> hubby = person[:]------------------------------------------------丈夫
>>> wifey = list(person)----------------------------------------------妻子
>>> son = person------------------------------------------------------儿子
>>> print person,hubby,wifey,son
['name', ['saving', 100]] ['name', ['saving', 100]] ['name', ['saving', 100]] ['name', ['saving', 100]]
>>> [id(x) for x in person,hubby,wifey,son]
[47203592L, 47203464L, 38922120L, 47203592L]---------------------仔细观察,发现person和son的id一致,他们的引用完全一致
>>> hubby[0],hubby[1][1] = 'joe',50-----------------------------------丈夫名字为joe  余额为50
>>> print person,hubby,wifey,son
['name', ['saving', 50]] ['joe', ['saving', 50]] ['name', ['saving', 50]] ['name', ['saving', 50]]-------------此时,神奇了,原来这是个公共账户!!!
为什么名字没有改变呢?
这个原因就是因为我们只是做了一个浅拷贝,浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象【saving,100。序列对象的浅拷贝是默认的拷贝类型,例如:切片操作;工厂函数list();dict,copy模块的copy函数
为什么账户的名字改变了,妻子儿子的名字却还是默认的呢?这是因为在这三个列表的两个对象中,第一个是字符串对象是不可变的,而第二个是列表对象是可变类型(子对象)。正因为如当进行浅拷贝时,字符串被显示的拷贝并创建了一个字符串对象,而list只是穿件了一个新的引用,并没有创建一个新的对象。所以改变名字是没有任何问题的。这就是一家人创建一个联合账户的绝佳方法啊!!!
另外一个例子:
>>> person = ['name',['saving',100]]
>>> l = person[:]
>>> [id(x) for x in person,l]
[47221512L, 47168200L]
>>> [id(x) for x in person]
[30262136L, 47211848L]
>>> [id(x) for x in l]
[30262136L, 47211848L]---------------
>>> l[0],l[1][1] = 'joe',50
>>> [id(x) for x in person]
[30262136L, 47211848L]
>>> [id(x) for x in l]
[45868616L, 47211848L]----------------看name变了,钱值变了但是id没变
>>> person,l
(['name', ['saving', 50]], ['joe', ['saving', 50]])

如果我们是要每个人有个独立的账户呢?这就需要深拷贝了。

>>> person = ['name',['saving',100]]
>>> hubby = person
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> [id(x) for x in person,hubby,wifey]
[47208200L, 47208200L, 47165576L]--------------------------hubby的id和person一样
>>> hubby[0],hubby[1][1]='joe',50---------------------------初始化hubby
>>> hubby,wifey,person
(['joe', ['saving', 50]], ['name', ['saving', 100]], ['joe', ['saving', 50]])---------诶?person也变了,但是wifey没变,这就得益于deepcopy了
>>> wifey[0],hubby[1][1]='jane',80-------------------------------------------------初始化wifey
>>> hubby,wifey,person
(['joe', ['saving', 80]], ['jane', ['saving', 100]], ['joe', ['saving', 80]])-------------诶?hubby和person都没变呢,这就得益于deepcopy
>>> [id(x) for x in person,hubby,wifey]
[47208200L, 47208200L, 47165576L]

几点关于拷贝操作的警告。第一,非容器类型(字符串,数字,和其他“原子”类型,xrange对象等)没有被拷贝一说。浅拷贝是用完全切片操作来完成的。第二,如果元组变量只包含原子类型,那么对他进行深拷贝也是无济于事的,也会表现为浅拷贝。
例子1:
tu2 =(1,2,[1,2])---------------元组变量包含非原子类型
>>> tu3 = copy.copy(tu2)
>>> tu2[2][1] = 5
>>> tu2
(1, 2, [1, 5])
>>> tu3
(1, 2, [1, 5])
>>> tu4 = copy.deepcopy(tu2)
>>> tu2[2][1] = 6
>>> tu4,tu3,tu2
((1, 2, [1, 5]), (1, 2, [1, 6]), (1, 2, [1, 6]))
例子2:
>>> person = ['name',('saving',100)]-----------元组变量只包含原子类型
>>> newp = copy.deepcopy(person)
>>> [id(x) for x in person,newp]
[47207752L, 47158472L]
>>> [id(x) for x in person]
[30262136L, 47124616L]
>>> [id(x) for x in newp]
[30262136L, 47124616L]----------------------id一样


阅读(248) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~