不同于C语言的变量与内存绑定的形式,python采用的引用机制,即变量指向内存地址。
首先提一下C语言中变量与内存的关系:变量与内存绑定。
当变量的值被改变时,实质上是该变量对应的内存中的数据发生了改变,而变量与内存间的绑定关系仍没变。即不管如何改变变量a的值,执行id(a)永远是相同的。
python中变量与内存的关系:变量指向内存。
当变量的值被改变时,原本的内存会被该变量舍弃,该变量会指向新的内存地址。(可变对象与不可变对象有不同的表现形式)
一、赋值语句:
import copy a = [9999999,'str',{1,2,3},[1,2],{'apple':10,'orange':5}] print('赋值语句'.center(50,'*')) b = a print('地址容器:',bool(id(a)==id(b))) print('不可变对象:',bool(id(a[0])==id(b[0]))) print('不可变对象:',bool(id(a[1])==id(b[1]))) print('可变对象:',bool(id(a[2])==id(b[2]))) print('可变对象:',bool(id(a[3])==id(b[3]))) print('可变对象:',bool(id(a[4])==id(b[4])))
输出如下:
***********************赋值语句***********************
地址容器: True
不可变对象: True
不可变对象: True
可变对象: True
可变对象: True
可变对象: True
二、浅拷贝
import copy a = [9999999,'str',{1,2,3},[1,2],{'apple':10,'orange':5}] print('浅复制'.center(50,'*')) c = copy.copy(a) print('地址容器:',bool(id(a)==id(c))) #列表与字典并不是直接存放数据,而是存放着数据的地址,进而通过地址找到数据。将存放各数据内存地址的称为地址容器(我自己取的) print('不可变对象:',bool(id(a[0])==id(c[0]))) print('不可变对象:',bool(id(a[1])==id(c[1]))) print('可变对象:',bool(id(a[2])==id(c[2]))) print('可变对象:',bool(id(a[3])==id(c[3]))) print('可变对象:',bool(id(a[4])==id(c[4])))
输出如下:
***********************浅复制************************
地址容器: False
不可变对象: True
不可变对象: True
可变对象: True
可变对象: True
可变对象: True
三、深拷贝
import copy a = [9999999,'str',{1,2,3},[1,2],{'apple':10,'orange':5}] print('深复制'.center(50,'*')) d = copy.deepcopy(a) print('地址容器:',bool(id(a)==id(d))) print('不可变对象:',bool(id(a[0])==id(d[0]))) print('不可变对象:',bool(id(a[1])==id(d[1]))) print('可变对象:',bool(id(a[2])==id(d[2]))) print('可变对象:',bool(id(a[3])==id(d[3]))) print('可变对象:',bool(id(a[4])==id(d[4])))
输出如下:
***********************深复制************************
地址容器: False
不可变对象: True
不可变对象: True
可变对象: False
可变对象: False
可变对象: False
四、分析
原本变量a的指向:
赋值语句:共享容器与数据。
在列表a中修改可变对象,b种对应的也会发生改变。
浅拷贝:容器不同,但共享数据。
在列表a中修改可变对象,b中对应的也会发生改变。
深拷贝:容器不同,共享不可变对象,不共享可变对象。
在列表a中修改可变对象,b中数据不会发生改变。