Python—深浅拷贝理解
目录:
- Python的可变数据类型及不可变数据类型
- Python浅拷贝
- Python深拷贝
一、Python的可变数据类型及不可变数据类型
-
首先在开始理解Python的深浅拷贝前,我们需要明白Python的数据类型中哪些属于可变数据类型,哪些属于不可变的数据类型。
-
Python不可变数据类型:
- Number(数字)
- String(字符串)
- Tuple(元组)
-
Python可变数据类型:
- Set(集合)
- List(列表)
- Dictionary(字典)
-
可变数据类型及不可变数据类型的定义:
-
可变数据类型:顾名思义,就是变量中对应的值是可以被修改的,即改了变量中对应的值的同时,内存地址不变。
-
不可变数据类型:就是变量中对应的值是不可以被修改的,即改了变量中对应的值的同时,内存地址也会改变。
-
对于两个(同一内存地址存储可变数据类型的数据)变量来说,当其中一个变量修改数据时,另一个变量所拿到的数据也是会发生改变。
-
对于两个(同一内存地址存储不可变数据类型的数据)变量来说,当其中一个变量修改数据时,实际上是Python开辟新的内存地址存储修改后的数据,并将这个新的内存地址给该变量,另一个变量不会影响。即修改存储不可变得数据类型的变量,实际上是开辟新的内存地址给该变量,而不是之前的内存地址。
-
下面是对可变数据类型和不可变数据类型的举例说明:
# 可变数据类型 a=[1,2,3] print("a:",a) print("内存地址:",id(a)) a.append(67) print("a:",a) print("内存地址:",id(a)) #上述代码运行结果: # a: [1, 2, 3] # 内存地址: 1819894616256 # a: [1, 2, 3, 67] # 内存地址: 1819894616256 # 不可变数据类型 b=1 print("b:",b) print("内存地址:",id(b)) b=2 print("b:",b) print("内存地址:",id(b)) #代码运行结果: # b: 1 # 内存地址: 140711594170016 # b: 2 # 内存地址: 140711594170048
-
二、Python浅拷贝
-
定义:对于顶层数据(如 [1,2,3,[‘a’,‘b’]] 中;一整个列表就是顶层元素)来说,假如顶层数据是可变数据类型,则会开辟新的内存地址来存储(仅对于顶层数据),而假如顶层数据是不可变数据类型,则是会直接复制内存地址,不会开辟新的内存地址;对于非顶层数据则是直接复制其内存地址。
-
下面是对浅拷贝的举例说明:
#温馨提示: #如果是要使用不是copy库中的copy方法,而是直接使用 a.copy(),被拷贝的数据必须是可变数据类型的,否则运行时会报错。 # 浅拷贝 import copy a=1 b=copy.copy(a) print("a 的内存地址为:",id(a)) print("b的内存地址为:",id(b)) #运行结果: # a 的内存地址为: 140711594170016 # b的内存地址为: 140711594170016 list1=[1,2,3,[55,'a']] list2=copy.copy(list1) print("list1的内存地址为:",id(list1)) print("list2的内存地址为:",id(list2)) print("list1[-1]:",list1[-1]) print("list2[-1]:",list2[-1]) print("list1[-1]的内存地址为:",id(list1[-1])) print("list2[-1]的内存地址为:",id(list2[-1])) list2[-1].append("jzj") print("修改list2[-1]的值后") print("list1的内存地址为:",id(list1)) print("list2的内存地址为:",id(list2)) print("list1[-1]:",list1[-1]) print("list2[-1]:",list2[-1]) print("list1[-1] 的内存地址为:",id(list1[-1])) print("list2[-1]的内存地址为:",id(list2[-1])) #运行结果: # list1的内存地址为: 1932912303680 # list2的内存地址为: 1932912394048 # list1[-1]: [55, 'a'] # list2[-1]: [55, 'a'] # list1[-1]的内存地址为: 1932912300096 # list2[-1]的内存地址为: 1932912300096 # 修改list2[-1]的值后 # list1的内存地址为: 1932912303680 # list2的内存地址为: 1932912394048 # list1[-1]: [55, 'a', 'jzj'] # list2[-1]: [55, 'a', 'jzj'] # list1[-1] 的内存地址为: 1932912300096 # list2[-1]的内存地址为: 1932912300096
三、Python深拷贝
-
定义:将变量中对应的值复制到在新的内存地址中,而不是复制数据对应的内存地址。
-
温馨提醒:在Python中无论是深拷贝还是浅拷贝,对于不可变类型的数据,都是复制其内存地址,而不是数据,因为一旦改变不可变类型的值,其内存地址也是会改变,所以复制其内存地址比复制其值能够提升性能、节省空间。
-
下面是对深拷贝的举例说明:
#深拷贝 import copy list1=[1,2,3,[55,'a']] list2=copy.deepcopy(list1) print("list1的内存地址为:",id(list1)) print("list2的内存地址为:",id(list2)) print("list1[0]的内存地址为:",id(list1[0])) print("list2[0]的内存地址为:",id(list2[0])) print("list1[-1]:",list1[-1]) print("list2[-1]:",list2[-1]) print("list1[-1]的内存地址为:",id(list1[-1])) print("list2[-1]的内存地址为:",id(list2[-1])) list2[-1].append("jzj") print("修改list2[-1]的值后") print("list1的内存地址为:",id(list1)) print("list2的内存地址为:",id(list2)) print("list1[-1]:",list1[-1]) print("list2[-1]:",list2[-1]) print("list1[-1] 的内存地址为:",id(list1[-1])) print("list2[-1]的内存地址为:",id(list2[-1])) #运行结果: # list1的内存地址为: 2107778465984 # list2的内存地址为: 2107778559936 # list1[0]的内存地址为: 140714265679520 # list2[0]的内存地址为: 140714265679520 # list1[-1]: [55, 'a'] # list2[-1]: [55, 'a'] # list1[-1]的内存地址为: 2107778469568 # list2[-1]的内存地址为: 2107778559232 # 修改list2[-1]的值后 # list1的内存地址为: 2107778465984 # list2的内存地址为: 2107778559936 # list1[-1]: [55, 'a'] # list2[-1]: [55, 'a', 'jzj'] # list1[-1] 的内存地址为: 2107778469568 # list2[-1]的内存地址为: 2107778559232