关于python深浅拷贝问题。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

时间:2021-01-02 19:49:03
关于python深浅拷贝问题。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
最近刚接触python,很多不太明白,还望各位帮忙疏通疏通。

15 个解决方案

#1


这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?

#2


感觉跟c,java有些不太一样,特别是这个关于内存地址引用这一块。

#3


引用 1 楼 trfizeng 的回复:
这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?


先第一个问题
你打印的是id(a[2]) id(b[2]) id(c[2])也就是['a','b']。深拷贝,浅拷贝当然不一样啊。
你不信执行a[2].append['c']
print a,b,c
这样就是c++一回事了,浅拷贝只是指针的复制,深拷贝会实际开辟一个新的内存
存储数据。

你在执行a[2][0] = 'X'
print a,b,c
你会发现c还是没有变换,你可以理解为id[a[2][0]]只是常量‘a’的地址。
a[2][0]='x'修改了a[2]对象第一个元素指向的地址,这个时候b[2]实际为同一对象,c[2]为不同对象,所以出现这样的结果。
python大部分都是引用,这个你要注意一下。

#4


不行,点击放大不了啊

#5


引用 3 楼 luo3380 的回复:
Quote: 引用 1 楼 trfizeng 的回复:

这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?


先第一个问题
你打印的是id(a[2]) id(b[2]) id(c[2])也就是['a','b']。深拷贝,浅拷贝当然不一样啊。
你不信执行a[2].append['c']
print a,b,c
这样就是c++一回事了,浅拷贝只是指针的复制,深拷贝会实际开辟一个新的内存
存储数据。

你在执行a[2][0] = 'X'
print a,b,c
你会发现c还是没有变换,你可以理解为id[a[2][0]]只是常量‘a’的地址。
a[2][0]='x'修改了a[2]对象第一个元素指向的地址,这个时候b[2]实际为同一对象,c[2]为不同对象,所以出现这样的结果。
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??

#6


引用 4 楼 sprawling 的回复:
不行,点击放大不了啊

鼠标移到图片出点击放大,麻烦了。

#7


浅拷贝,只复制第一层对象,深拷贝,复制所有嵌套层对象。

#8


引用 7 楼 u013171165 的回复:
浅拷贝,只复制第一层对象,深拷贝,复制所有嵌套层对象。

比如这样,
a=[1,2,['m','n']],
b=copy.copy(a),
c=copy.deepcopy(a),
此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝的c[0]也会跟他们相等?
再说,那我删除了a[0],为什么b,c中的a[0]都还在?
他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?
为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾?? 

#9


引用 5 楼 trfizeng 的回复:
Quote: 引用 3 楼 luo3380 的回复:

...
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??


一个list就像一个通讯录,你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,不会影响别的通讯录。

至于为什么c[0]和a[0]是同一对象,在copy模块的文档里说:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

所以deepcopy的实现中也没有复制像数值,字符串这样的基本类型。下面是copy模块中的相关代码,int,long, tuple等所用的copy函数都是 _copy_immutable, 而 _copy_immutable所做的就是直接返回要copy的值。


def _copy_immutable(x):
    return x
for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable                  # d是一个字典,记录各个类型的值对应的copy的办法
def _copy_with_constructor(x):          # 和list,dict的copy方法对比,可以看出两者的不同
    return type(x)(x)
for t in (list, dict, set):
    d[t] = _copy_with_constructor

#10


引用 9 楼 panghuhu250 的回复:
Quote: 引用 5 楼 trfizeng 的回复:

Quote: 引用 3 楼 luo3380 的回复:

...
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??


一个list就像一个通讯录,你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,不会影响别的通讯录。

至于为什么c[0]和a[0]是同一对象,在copy模块的文档里说:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

所以deepcopy的实现中也没有复制像数值,字符串这样的基本类型。下面是copy模块中的相关代码,int,long, tuple等所用的copy函数都是 _copy_immutable, 而 _copy_immutable所做的就是直接返回要copy的值。


def _copy_immutable(x):
    return x
for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable                  # d是一个字典,记录各个类型的值对应的copy的办法
def _copy_with_constructor(x):          # 和list,dict的copy方法对比,可以看出两者的不同
    return type(x)(x)
for t in (list, dict, set):
    d[t] = _copy_with_constructor

好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。

#11


引用 10 楼 trfizeng 的回复:
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


#3说:
引用 3 楼 luo3380 的回复:
...
python大部分都是引用,这个你要注意一下。


一个list就像一个通讯录,每一条记录指向一个人,但那些人是独立于通讯录存在的。你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,结果是你无法在根据你的通讯录找到那个人,但那个人还是存在的,不会影响别的通讯录。

#12



好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


因为是引用计数方式管理对象,上面说没拷贝其实是增加了引用数,所以删除是减少引用,直到引用为0丢进回收机制,也不一定立马删除...
>>> import sys
>>> id(1), id(2)
(27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(834, 327)
>>> a = b = 1
>>> c = 2
>>> id(a), id(b), id(c)
(27000368, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(836, 328)
>>> a = 2
>>> id(a), id(b), id(c)
(27000356, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(835, 329)
>>> 

#13


楼上分析得很清晰,学习了

#14


引用 12 楼 angel_su 的回复:

好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


因为是引用计数方式管理对象,上面说没拷贝其实是增加了引用数,所以删除是减少引用,直到引用为0丢进回收机制,也不一定立马删除...
>>> import sys
>>> id(1), id(2)
(27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(834, 327)
>>> a = b = 1
>>> c = 2
>>> id(a), id(b), id(c)
(27000368, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(836, 328)
>>> a = 2
>>> id(a), id(b), id(c)
(27000356, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(835, 329)
>>> 

>>> import copy
>>> a=[1,2]
>>> b=copy.copy(a)
>>> b
[1, 2]
>>> c=copy.deepcopy(a)
>>> c
[1, 2]
>>> id(a[0]),id(b[0]),id(c[0])
(31403112, 31403112, 31403112)  #引用同一对象1
>>> a.remove(a[0])
>>> a,b,c
([2], [1, 2], [1, 2])  #这里为什么a中的a[0]立马就执行删除了,b[0],c[0]还在啊?
>>>

#15


这是我比较疑惑的地方。

#1


这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?

#2


感觉跟c,java有些不太一样,特别是这个关于内存地址引用这一块。

#3


引用 1 楼 trfizeng 的回复:
这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?


先第一个问题
你打印的是id(a[2]) id(b[2]) id(c[2])也就是['a','b']。深拷贝,浅拷贝当然不一样啊。
你不信执行a[2].append['c']
print a,b,c
这样就是c++一回事了,浅拷贝只是指针的复制,深拷贝会实际开辟一个新的内存
存储数据。

你在执行a[2][0] = 'X'
print a,b,c
你会发现c还是没有变换,你可以理解为id[a[2][0]]只是常量‘a’的地址。
a[2][0]='x'修改了a[2]对象第一个元素指向的地址,这个时候b[2]实际为同一对象,c[2]为不同对象,所以出现这样的结果。
python大部分都是引用,这个你要注意一下。

#4


不行,点击放大不了啊

#5


引用 3 楼 luo3380 的回复:
Quote: 引用 1 楼 trfizeng 的回复:

这个图怎么这么小啊,麻烦点击放大看,有劳各位了。
现在主要混淆的地方就是在python中,
疑惑1:如a=10,b=10,a,b的地址就是一样的,我可否这样理解,python是以内容为基准的,这时a,b都共享10,只有一份10?
疑惑2:如果是这样理解的话,那么深浅拷贝的时候,a=[1,2,['a','b']],浅拷贝b=copy.copy(a),深拷贝c=copy.deepcopy(a),这时a[0]、b[0]、c[0]他们的地址都是一样,为啥我a中删除了a[0],b、c中还存在?
疑惑3:a[2]和b[2]地址相同,为何c[2]不同?
疑惑4:我就是认为地址一样,他们就是共享的,任何一方删除都会对其他产生影响?


先第一个问题
你打印的是id(a[2]) id(b[2]) id(c[2])也就是['a','b']。深拷贝,浅拷贝当然不一样啊。
你不信执行a[2].append['c']
print a,b,c
这样就是c++一回事了,浅拷贝只是指针的复制,深拷贝会实际开辟一个新的内存
存储数据。

你在执行a[2][0] = 'X'
print a,b,c
你会发现c还是没有变换,你可以理解为id[a[2][0]]只是常量‘a’的地址。
a[2][0]='x'修改了a[2]对象第一个元素指向的地址,这个时候b[2]实际为同一对象,c[2]为不同对象,所以出现这样的结果。
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??

#6


引用 4 楼 sprawling 的回复:
不行,点击放大不了啊

鼠标移到图片出点击放大,麻烦了。

#7


浅拷贝,只复制第一层对象,深拷贝,复制所有嵌套层对象。

#8


引用 7 楼 u013171165 的回复:
浅拷贝,只复制第一层对象,深拷贝,复制所有嵌套层对象。

比如这样,
a=[1,2,['m','n']],
b=copy.copy(a),
c=copy.deepcopy(a),
此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝的c[0]也会跟他们相等?
再说,那我删除了a[0],为什么b,c中的a[0]都还在?
他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?
为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾?? 

#9


引用 5 楼 trfizeng 的回复:
Quote: 引用 3 楼 luo3380 的回复:

...
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??


一个list就像一个通讯录,你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,不会影响别的通讯录。

至于为什么c[0]和a[0]是同一对象,在copy模块的文档里说:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

所以deepcopy的实现中也没有复制像数值,字符串这样的基本类型。下面是copy模块中的相关代码,int,long, tuple等所用的copy函数都是 _copy_immutable, 而 _copy_immutable所做的就是直接返回要copy的值。


def _copy_immutable(x):
    return x
for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable                  # d是一个字典,记录各个类型的值对应的copy的办法
def _copy_with_constructor(x):          # 和list,dict的copy方法对比,可以看出两者的不同
    return type(x)(x)
for t in (list, dict, set):
    d[t] = _copy_with_constructor

#10


引用 9 楼 panghuhu250 的回复:
Quote: 引用 5 楼 trfizeng 的回复:

Quote: 引用 3 楼 luo3380 的回复:

...
python大部分都是引用,这个你要注意一下。

首先非常谢谢你的回答。我想问下。
浅拷贝只是复制父对象,深拷贝会复制父子对象,所以他们相当于独立出来了,这个我明白,比如这样,a=[1,2,['m','n']],b=copy.copy(a),c=copy.deepcopy(a),此时发现id(a[0])==id(b[0])==id(c[0]),为什么深拷贝也会跟他们相等?再说,那我删除了a[0],为什么b,c中的a[0]都还在?他们既然地址一样,说明就是都指向同一处,不是说深拷贝连子对象也要拷贝吗?为什么c[0]的地址也等于a[0]地址会相等。越想越矛盾??


一个list就像一个通讯录,你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,不会影响别的通讯录。

至于为什么c[0]和a[0]是同一对象,在copy模块的文档里说:

The difference between shallow and deep copying is only relevant for
compound objects (objects that contain other objects, like lists or
class instances).

所以deepcopy的实现中也没有复制像数值,字符串这样的基本类型。下面是copy模块中的相关代码,int,long, tuple等所用的copy函数都是 _copy_immutable, 而 _copy_immutable所做的就是直接返回要copy的值。


def _copy_immutable(x):
    return x
for t in (type(None), int, long, float, bool, str, tuple,
          frozenset, type, xrange, types.ClassType,
          types.BuiltinFunctionType, type(Ellipsis),
          types.FunctionType, weakref.ref):
    d[t] = _copy_immutable                  # d是一个字典,记录各个类型的值对应的copy的办法
def _copy_with_constructor(x):          # 和list,dict的copy方法对比,可以看出两者的不同
    return type(x)(x)
for t in (list, dict, set):
    d[t] = _copy_with_constructor

好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。

#11


引用 10 楼 trfizeng 的回复:
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


#3说:
引用 3 楼 luo3380 的回复:
...
python大部分都是引用,这个你要注意一下。


一个list就像一个通讯录,每一条记录指向一个人,但那些人是独立于通讯录存在的。你复制了一份(无论是抄录了一份(shallow copy)还是制造了一个镜像世界,同时复制了通讯录里的人(deep copy)),然后你把原来通讯录中的记录划掉一个,结果是你无法在根据你的通讯录找到那个人,但那个人还是存在的,不会影响别的通讯录。

#12



好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


因为是引用计数方式管理对象,上面说没拷贝其实是增加了引用数,所以删除是减少引用,直到引用为0丢进回收机制,也不一定立马删除...
>>> import sys
>>> id(1), id(2)
(27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(834, 327)
>>> a = b = 1
>>> c = 2
>>> id(a), id(b), id(c)
(27000368, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(836, 328)
>>> a = 2
>>> id(a), id(b), id(c)
(27000356, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(835, 329)
>>> 

#13


楼上分析得很清晰,学习了

#14


引用 12 楼 angel_su 的回复:

好像明白了点,原来是深拷贝在基本数字类型没做拷贝,
才导致id(a[0]) == id(b[0]) ==id(c[0]),
我还是明太明白,a[0] = 1,a[0]、b[0]、c[0]都指向1,既然基本数字类型没作拷贝就说明无论深浅拷贝都是指向同一对象,
那无论任何一方删除其他都会受影响啊,比如a.remove(a[0])的时候为啥b[0]、c[0]还存在,这个怎么解释,还是我哪里理解错了?麻烦告知。。。


因为是引用计数方式管理对象,上面说没拷贝其实是增加了引用数,所以删除是减少引用,直到引用为0丢进回收机制,也不一定立马删除...
>>> import sys
>>> id(1), id(2)
(27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(834, 327)
>>> a = b = 1
>>> c = 2
>>> id(a), id(b), id(c)
(27000368, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(836, 328)
>>> a = 2
>>> id(a), id(b), id(c)
(27000356, 27000368, 27000356)
>>> sys.getrefcount(1), sys.getrefcount(2)
(835, 329)
>>> 

>>> import copy
>>> a=[1,2]
>>> b=copy.copy(a)
>>> b
[1, 2]
>>> c=copy.deepcopy(a)
>>> c
[1, 2]
>>> id(a[0]),id(b[0]),id(c[0])
(31403112, 31403112, 31403112)  #引用同一对象1
>>> a.remove(a[0])
>>> a,b,c
([2], [1, 2], [1, 2])  #这里为什么a中的a[0]立马就执行删除了,b[0],c[0]还在啊?
>>>

#15


这是我比较疑惑的地方。