《Dive.Into.Python》学习中的问题(与copy模块有关)
在学习《Dive.Into.Python》时碰到一个问题,写出来向高手请教,正在学这本书的朋友也请讨论一下。
在书的5.5节“例 5.10. UserDict 常规方法”中有以下函数定义
def copy(self):
if self.__class__ is UserDict:
return UserDict(self.data)
import copy
return copy.copy(self)
书上的解释是“如果 self.__class__ 不是 UserDict,那么 self 一定是 UserDict 的某个子类(如可能为 FileInfo),UserDict 不知道如何生成它的子类的一个原样的拷贝,所以我们只能完全复制它们,确定拷贝了它们的全部内容。幸运的是,Python 带了一个模块可以正确地完成这件事,它叫做 copy。 copy 能够拷贝任何 Python 对象就够了,这就是为什么我们在这里用它的原因。”
我的问题是:既然copy模块可以拷贝任何对象,为什么还要用if语句判断,而不是直接用copy模块进行拷贝?那样不是更简洁吗?
请高手不吝赐教,正在看这本书的朋友也请讨论一下。
[解决办法]
因为UserDict的成员变量dict实际上是指向一个字典对象实体的引用.类似于C语言中的指针.
copy.copy只是把对象成员的值复制一遍,成成员的引用并不复制,这样copy后新的Userdict的的data成员同原来UserDict的data成员指向同一个 对象实体. 改变前者,也就改变了后者.可能带来潜在的问题.
src = UserDict({3:7})
dest = copy.copy( src)
dest[9] = 8
print src
可以看到src中也有key为9了. 这不符合copy的语义. (用deepcopy可以实现内容复制, 但需要注意层数)
UserDict的__init__方法,是dict的内容复制,而不是引用复制.
def __init__(self, dict=None):
self.data = {}
if dict is not None: self.update(dict)