# Python中的引用与直接赋值、浅拷贝和深拷贝

本文详细介绍了Python中引用的概念,包括函数参数传递时可变类型与不可变类型的差异。接着,通过实例展示了直接赋值、浅拷贝和深拷贝的区别,强调了它们在处理对象及子对象时内存地址的变化,帮助读者理解Python中对象复制的深层次原理。
摘要由CSDN通过智能技术生成

Python中的引用与浅拷贝和深拷贝

python中的引用

Python中不允许程序员选择传值还是传引用。函数参数传递采用的是“传对象引用”。简而言之,若参数是可变类型[字典、列表、集合] 即不能被哈希的对象,就能修改对象的原始值;若参数是不可变类型[数值、字符、元组]即能被哈希的对象,就不能修改对象原始值。

例:可变类型的引用

p1 = [1,2,3]
def list_1(p):
    p = p+[1]
    print(p)
    print(id(p))
list_1(p1)
print(p1)
print(id(p1))
>>>[1, 2, 3, 1]
>>>2060407209792
>>>[1, 2, 3]
>>>2060405764736

p2 = [1,2,3]
def list_2(p):
    p +=[1]
    print(p)
    print(id(p))
list_2(p2)
print(p2)
print(id(p2))
>>>[1, 2, 3, 1]
>>>2060407209792
>>>[1, 2, 3, 1]
>>>2060407209792

上述两个函数,之所以输出结果不同,是因为“=”操作符是在内存中创建一个新变量p保存赋值结果,即所谓“传值”,通过观察他们的ID不同,我们也能理解。而“+=”操作符则是直接对传入的p2修改,即所谓“传引用”,他们的ID也相同,符合推断。

例:不可变类型的引用

a = 100
def list_1(p):
    p = p+100
    print(p)
    print(id(p))
list_1(a)
print(a)
print(id(a))
>>>200
>>>140709999032288
>>>100
>>>140709999029088


b = 1000
def list_2(p):
    p +=100
    print(p)
    print(id(p))
list_2(b)
print(b)
print(id(b))
>>>1100
>>>3033967515952
>>>1000
>>>3033966466800

由于数值是不可变类型,所以无论操作符是“=”或者“+=”,都是采用”传值“ 的方式进行参数传参,观察他们的ID也可以发现,四个ID都各不相同。

python中的直接赋值、浅拷贝和深拷贝

直接赋值”=“:就是对象的引用。

浅拷贝:拷贝父对象,不会拷贝对象的内部的子对象

深拷贝:使用copy模块的 deepcopy 方法,完全拷贝父对象及其子对象

#直接赋值  列表实例
list3 = [123, 456]
print(id(list3))
list5 = list3
print(list5)
print(id(list5))
list3[0]=1
print(list3)
print(id(list3))
print(list5)
print(id(list5))
>>>2164292645056
>>>[123, 456]
>>>2164292645056
>>>[1, 456]
>>>2164292645056
>>>[1, 456]
>>>2164292645056

#浅拷贝 字典实例
a = {1:[1,2,3]}
b = a.copy()
print(a,b)
print(id(a),id(b))
a[1].append(4)
print(a,b)
print(id(a[1]),id(b[1]))
>>>{1: [1, 2, 3]} {1: [1, 2, 3]}
>>>2539185110080 2539185110144
>>>{1: [1, 2, 3, 4]} {1: [1, 2, 3, 4]}
>>>2539185173120 2539185173120
#深拷贝 字典实例
import copy
a = {1:[1,2,3]}
c = copy.deepcopy(a)
print(a,c)
print(id(a),id(c))
a[1].append(5)
print(a,c)
print(id(a[1]),id(c[1]))
>>>{1: [1, 2, 3]} {1: [1, 2, 3]}
>>>2258846940160 2258852622272
>>>{1: [1, 2, 3, 5]} {1: [1, 2, 3]}
>>>2258853762240 2258853762432

1.观察直接赋值实例可得,list3和list5其实在内存中都指向同一地址,即指向同一个对象

2.观察浅拷贝实例可得,浅拷贝下的a和b是一个独立个体,在内存中有不同的地址,但他们的子对象,仍然指向统一对象(引用)

3.观察深拷贝实例可得,深拷贝下的a和b是一个独立个体,在内存中有不同的地址,同时他们的子对象,也是独立个体,在内存中拥有不同的地址。

总结

引用的关键是分清函数传参时,参数对象到底是可变类型还是不可变类型。可变类型传参效果类似”传引用“;不可变类型传参效果类似”传值“

直接赋值、浅拷贝和深拷贝关键在于弄清楚他们的子对象是独立个体还是统一引用,通过观察他们的ID可以比较清楚的理解它们的不同。

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值