Python数据结构与算法(11)---对象的非永久引用weakref

简介: Python数据结构与算法(11)---对象的非永久引用weakref

对象的非永久引用weakref


weakref库支持对象的弱引用。正常的引用会增加对象的引用数,并避免它被垃圾回收。但结果并不总是期望的那样。


比如,有时候可能会出现一个循环引用,或者有时候需要内存时,可能要删除对象的缓存。而弱引用是一个不能避免对象被自动清理的对象句柄。


引用

下面,我们来看一个简单的例子,示例如下:

import weakref
class MyObject:
    def __del__(self):
        print('删除{}'.format(self))
obj = MyObject()
r = weakref.ref(obj)
print('obj:', obj)
print('ref:', r)
print('r():', r())
print("删除对象引用")
del obj
print('r():', r())


运行之后,控制台输出如下:


这里对象的弱引用需要通过ref类来管理,要获取原对象,可以调用引用对象。这里,由于obj在第二次调用引用之前已经被删除,所以ref返回None。


引用回调

ref的构造函数还有一个可选参数,删除所所应用的对象时,会调用这个函数,也就是java里常说的回调函数。示例如下:

import weakref
class MyObject:
    def __del__(self):
        print('删除{}'.format(self))
def callBack(reference):
    print('callback{}'.format(reference))
obj = MyObject()
r = weakref.ref(obj, callBack)
print('obj:', obj)
print('ref:', r)
print('r():', r())
print("删除对象引用")
del obj
print('r():', r())


相对于前面的代码,除了多出一个方法,以及一个参数之外,其他的代码一模一样。运行之后,效果如下:


当引用已经死亡,不再引用原对象时,就会触发这个回调函数。因为回调函数接收的参数是引用对象,所以这个特性的一种用法是从缓存中删除弱引用对象。


最终化对象

清理弱引用时要对资源完成更健壮的管理,可以使用finalize将回调与对象关联。finalize实例会一直保留,直到所关联的对象被删除,即使应用并没有保留最终化对象的引用。


示例如下:

import weakref
class MyObject:
    def __del__(self):
        print('删除{}'.format(self))
def on_finalize(*args):
    print('on_finalize-----{}'.format(args))
obj=MyObject()
weakref.finalize(obj,on_finalize,'额外参数')
del obj


运行之后,效果如下:


finalize参数包括要跟踪对象,对象被垃圾回收时要调用的回调函数on_finalize以及传入这个回调函数的所有位置或命令参数。


不过,finalize还有一个属性atexit,它用来控制程序退出时是否调用这个回调(如果还没有调用的话),示例如下:

f = weakref.finalize(obj, on_finalize, '额外参数')
f.atexit = False


这里,只需要改变最后两行代码,运行不会有任何结果。这是因为设置atexit为False表示不调用这个回调。


需要注意的是,因为finalize跟踪了一个对象的一个引用,那么便会导致这个对象引用被保留,所以这个对象永远不会被垃圾回收。


代理

有时候使用代理比使用弱引用更方便。使用代理可以像使用原对象一样,而且不要求再访问对象之前先调用代理。


这说明,可以将代理传递到一个库,而这个库并不知道它接收的是一个引用而不是真正的对象。


示例如下:

import weakref
class MyObject:
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print('删除{}'.format(self))
obj = MyObject("MyObject")
r = weakref.ref(obj)
p = weakref.proxy(obj)
print('obj:', obj.name)
print('ref:', r().name)
print('proxy:', p.name)
del obj
print('proxy:', p.name)


运行之后,效果如下:

可以看到,如果引用对象已经被删除,那么再访问代理会产生一个ReferenceError异常。


缓存对象

ref和proxy类被认为是底层的。尽管它们对于维护单个对象的弱引用很有用,并且还支持对循环引用的垃圾回收。


但WeakKeyDictionary和WeakValueDictionary类为创建多个对象的缓存提供了一个更合适的API。


WeakValueDictionary类使用它包含的值的弱引用,当其他代码不再真正使用这些值时,则允许垃圾回收。


利用垃圾回收器的显式调用,下面展示了使用常规字典和WeakValueDictionary完成内存处理的区别。

import weakref
import gc
from pprint import pprint
gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
class MyObject:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'MyObject---{}'.format(self.name)
    def __del__(self):
        print('删除---{}'.format(self))
def demo(cache_factory):
    all_refs = {}
    print('缓存类型:', cache_factory)
    cache = cache_factory()
    for name in ['one', 'two', 'three']:
        o = MyObject(name)
        cache[name] = o
        all_refs[name] = o
        del o
    print(" all_refs=", end='')
    pprint(all_refs)
    print("开始 缓存包括:", list(cache.keys()))
    for name, value in cache.items():
        print('{}={}'.format(name, value))
        del value
    print('清理')
    del all_refs
    gc.collect()
    print('结束 缓存包括:', list(cache.keys()))
    for name, value in cache.items():
        print('{}={}'.format(name, value))
    print("返回")
    return
demo(dict)
print()
demo(weakref.WeakValueDictionary)


运行之后,效果如下:


如上图所示,如果循环变量指示所缓存的值,那么这些循环变量必须被显式清除,以使对象的引用数减少。否则,垃圾回收器不会删除这些对象,它们仍然会保留在缓存中。类似地,all_refs变量用来保存引用,以防止它们被过早地垃圾回收。

相关文章
|
23天前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
2月前
|
监控 算法 安全
深度洞察内网监控电脑:基于Python的流量分析算法
在当今数字化环境中,内网监控电脑作为“守城卫士”,通过流量分析算法确保内网安全、稳定运行。基于Python的流量分析算法,利用`scapy`等工具捕获和解析数据包,提取关键信息,区分正常与异常流量。结合机器学习和可视化技术,进一步提升内网监控的精准性和效率,助力企业防范潜在威胁,保障业务顺畅。本文深入探讨了Python在内网监控中的应用,展示了其实战代码及未来发展方向。
|
2月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
173 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
14天前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
42 12
|
12天前
|
算法 安全 网络安全
基于 Python 的布隆过滤器算法在内网行为管理中的应用探究
在复杂多变的网络环境中,内网行为管理至关重要。本文介绍布隆过滤器(Bloom Filter),一种高效的空间节省型概率数据结构,用于判断元素是否存在于集合中。通过多个哈希函数映射到位数组,实现快速访问控制。Python代码示例展示了如何构建和使用布隆过滤器,有效提升企业内网安全性和资源管理效率。
45 9
|
20天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
35 10
|
2月前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
57 17
|
2月前
|
存储 监控 算法
员工电脑监控屏幕场景下 Python 哈希表算法的探索
在数字化办公时代,员工电脑监控屏幕是保障信息安全和提升效率的重要手段。本文探讨哈希表算法在该场景中的应用,通过Python代码例程展示如何使用哈希表存储和查询员工操作记录,并结合数据库实现数据持久化,助力企业打造高效、安全的办公环境。哈希表在快速检索员工信息、优化系统性能方面发挥关键作用,为企业管理提供有力支持。
50 20
|
10天前
|
存储 算法 量子技术
解锁文档管理系统高效检索奥秘:Python 哈希表算法探究
在数字化时代,文档管理系统犹如知识宝库,支撑各行各业高效运转。哈希表作为核心数据结构,通过哈希函数将数据映射为固定长度的哈希值,实现快速查找与定位。本文聚焦哈希表在文档管理中的应用,以Python代码示例展示其高效检索特性,并探讨哈希冲突解决策略,助力构建智能化文档管理系统。
|
2月前
|
存储 人工智能 算法
深度解密:员工飞单需要什么证据之Python算法洞察
员工飞单是企业运营中的隐性风险,严重侵蚀公司利润。为应对这一问题,精准搜集证据至关重要。本文探讨如何利用Python编程语言及其数据结构和算法,高效取证。通过创建Transaction类存储交易数据,使用列表管理订单信息,结合排序算法和正则表达式分析交易时间和聊天记录,帮助企业识别潜在的飞单行为。Python的强大功能使得从交易流水和沟通记录中提取关键证据变得更加系统化和高效,为企业维权提供有力支持。

热门文章

最新文章