对python赋值的一点小小理解
操作方法
- 01
众所周知,Python的赋值和一般的高级语言的赋值有很大的不同,它是引用赋值。看下面的代码1: >>>a = 5 >>>b = 8 >>> a = b #结果如下图1: 图1 开始的时候a指向的是5,b指向的是8,当a = b的时候,b把自己指向的地址(也就是8的内存地址)赋给了a,那么最后的结果就是a和b同时指向了8。我们可以用Python内建的函数id()来测试 那好,现在我们来看下一种情况: >>>a = [1,2,3] >>>id(a ) #可以得到1217620 >>>a.append(4) #这时候a = [1,2,3,4], >>>id(a) #结果还是1217620,证明如果是添加对象,不改变变量的内存地址,这个是我们下面要探讨的问题的先决条件。 >>>b = a # b = [1,2,3,4] >>>a.append(5) #a = b = [1,2,3,4,5] 如果没有上面的结论,[1,2,3,4]的地址和[1,2,3]的地址不一样,那么最终的结果是 a = [1,2,3,4,5], b = [1,2,3,4] 那怎么才能够让a变成[1,2,3,4],而b仍然是[1,2,3]呢? 这个时候我们需要用到copy,也就是拷贝,python内置了copy模块。看代码2 >>>import copy >>>a = [1,2,3] >>>b = copy.copy(a) #这个时候a = b = [1,2,3] >>>a.append(4) # a = [1,2,3,4],b = [1,2,3] 事情到这里好像就结束了,但是问题又来啦,看下面的代码3 >>>import copy >>>a = [1,2,[3,4]] >>>b = copy.copy(a) >>>id(a) #12177080 >>>id(b) #12186888,证明a、b指向的不是同一个地址 >>>a[2].append(5) # 这时候a = b = [1,2,[3,4,5]],怎么会这样???? >>>id(a[0]) # 100380032 >>>id(b[0]) # 100380032 二者是共享地址的 也就是说这个copy.copy复制的不彻底,只复制了对象,对象的属性却是共享的。那我们有别的方法没?答案是肯定的,看下面的代码4 >>>import copy >>>a = [1,2,[3,4]] >>>b = copy.deepcopy(a) >>>id(a) #12177080 >>>id(b) #12177000 >>>a[2].append(5) #这时候 a = [1,2,[3,4,5]],而 b = [1,2,[3,4]] >>>id(a[2][1]) #10379996 >>>id(b[2][1]) #10379996 这两个还是一样的,大惑不解,这是为什么?求达人解惑 经过linvo同学的指点,现在明白了为什么是这样。下面画个图: 如果只是浅拷贝(copy.copy),那么虚线部分是不会赋值给b的,只是把 [3,4]这个列表整体赋值。所以结果如代码3所示 而如果是深拷贝(copy.deepcopy),那么会把列表[3,4]的具体成员也赋给b,这也解释了代码4的疑惑 未完待续。。。。。。。。。。。。。。。。。