Python引用复制,参数传递,弱引用与垃圾回收
引用#
先上个示例:
>>> val = [1]
>>> val[0] = val
>>> val
[[...]]
上述代码使val中包含自身,而产生了无限递归。上述示例表明Python中的变量名为引用类型,赋值只是使得左值指向与右值相同的内存对象。
is
运算符可以判断两个引用是否指向了同一个对象,而==
运算符判断两个引用指向的值是否相等而不关心指向什么对象。
对引用不了解的朋友,可以把Python引用与C/C++中的void *
类比,不过因为垃圾回收机制Python引用无需担心内存泄漏的问题。
复制#
上面的示例表明赋值无法为对象建立副本,python中的copy模块提供了copy
和deepccopy
建立副本。
示例:
>>> import copy
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(7)
>>> a[1][2] = 0
>>> a
[[1, 2, 3], [4, 5, 0], 7]
>>> b
[[1, 2, 3], [4, 5, 0], 7]
>>> c
[[1, 2, 3], [4, 5, 0]]
>>> d
[[1, 2, 3], [4, 5, 6]]
浅复制copy.copy只复制父引用指向的对象,其子引用仍指向原来的内存对象,而深复制copy.deepcopy
则会复制所有引用指向的对象。deepcopy 本质上是递归 copy。
示例中的副本c,d父对象是a的副本所以a.append
方法对它们没有影响。
但是copy.copy
创建的副本c中的元素仍指向与a相同的内存对象,而deepcopy
创建的d则指向了自己的元素。
tuple和frozenset之类的容器只是保证其中引用指向不变,但是引用指向的内存对象仍然是可变的。容器的切片对象的机制为浅复制。
x = x + y
,必须创建新的临时变量然后进行浅复制,性能较差。
x += y
,无需新建临时对象,只在内存块末尾增加元素,性能较好。
参数传递#
Python中的参数传递采用浅复制的值传递。
示例:
>>> def swap(a,b):
... b,a=a,b
...
>>> a = 1
>>> b = 2
>>> swap(1,2)
>>> a
1
>>> b
2
上述示例证明,Python参数传递是采用值传递的方式。
示例2:
>>> def fun(a):
... a[0] = 2
...
>>> a = [1]
>>> fun(a)
>>> a
[2]
这个示例则证明采用浅复制的方法进行传递。
垃圾回收#
Python中的垃圾回收是以引用计数为主,标记-清除和分代收集为辅。
一组对象互相引用的情况称为循环引用(交叉引用),若出现这种情况引用计数将无法正确的回收垃圾。,可以包含其他对象引用的容器对象(如list, dict, set,甚至class)都可能产生循环引用。
标记 - 清除#
“标记-清除”法是为了解决循环引用问题。
垃圾标记时,先将集合中对象的引用计数复制一份副本(以免在操作过程中破坏真实的引用计数值),然后操作这个副本,遍历对象集合,将被引用对象的引用计数副本值减1。
根据引用计数副本值是否为0将集合内的对象分成两类,reachable和unreachable,其中unreachable是可以被回收的对象。
分代回收#
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
弱引用#
弱引用是避免循环引用的一种方法,弱引用不记录引用计数。当一个对象只有弱引用时可能被垃圾回收器回收。
weakref.ref(obj,[callable])
用于建立一个指向obj的弱引用,当对象被回收前callable可选参数指定的函数将被执行以进行清理工作。
作者:finley
出处:https://www.cnblogs.com/Finley/p/5317072.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!