python的弱引用指引用一个对象但不增加它的引用计数器。这么做的好处是什么呢?什么时候需要考虑用若引用呢?

假设我们在设计一个游戏,有一个角色类Char,我们要给他添加一个效果(比如中毒),于是设计了一个效果类Effect。现在,给角色增加效果看上去就像这样:

  1. char.effect = Effect() # 给角色添加一个效果

每个效果生效的时机都是不同的,为了方便复用,我们再设计一个激活策略类ActivePloy,负责激活效果。于是在Effect和ActivePloy的内部看上去就像这样:

  1. class Effect(object):
  2. def __init__(self):
  3. self.active_ploy = ActivePloy(self)
  4. def active(self):
  5. """激活时的处理"""
  6. pass
  7. class ActivePloy(object):
  8. def __init__(self, effect):
  9. self.effect = effect
  10. def active(self):
  11. """激活时,激活对应效果"""
  12. self.effect.active()

这样做的好处是Effect不用关心自己何时激活,激活的判断都放给ActivePloy来处理。看上去挺好的,但是,这里面有一个问题,就是当我们试图给玩家去掉这个效果时……

  1. del char.effect

仔细想想,这么干以后,Effect的实例其实是没有被回收的,因为Effect和ActivePloy交叉引用,他们的引用计数都为1。

那么我们为了干净的删除effect,似乎就只能手动的来清理一下他们之间的这个交叉引用了:

  1. class Effect(object):
  2. def __init__(self):
  3. self.active_ploy = ActivePloy(self)
  4. def active(self):
  5. """激活时的处理"""
  6. pass
  7. def destroy(self):
  8. self.active_ploy.destroy()
  9. class ActivePloy(object):
  10. def __init__(self, effect):
  11. self.effect = effect
  12. def active(self):
  13. """激活时,激活对应效果"""
  14. self.effect.active()
  15. def destroy(self):
  16. self.effect = None

于是我们要删除一个效果,就得这样:

  1. char.effect.destroy()
  2. del char.effect

太麻烦了,不是吗?而且万一一个效果有多个激活策略的话,必须保证Effect把每个ActivePloy的destroy方法都运行一遍,漏了一个都无法保证自身被干净的删除。

我们来分析一下,之所以这么麻烦,就是因为ActivePloy对Effect有一个引用。那么如果ActivePloy不引用Effect不就OK了?这个时候,让我们来试试弱引用。

  1. import weakref
  2. class Effect(object):
  3. def __init__(self):
  4. self.active_ploy = ActivePloy(self)
  5. def active(self):
  6. """激活时的处理"""
  7. pass
  8. class ActivePloy(object):
  9. def __init__(self, effect):
  10. self.effect = weakref.proxy(effect) # 弱引用effect
  11. def active(self):
  12. """激活时,激活对应效果"""
  13. self.effect.active()

代码只有一个地方改变了,就是

  1. self.effect = weakref.proxy(effect)

这句的效果就是self.effect可以像往常一样的使用,但是却不会增加effect的引用计数器。换言之,这样写,他们之间的交叉关系消失了!这个时候我们只需要单纯的删掉char.effect,Effect和ActivePloy的实例都会被销毁。

什么,假设ActivePloy在其他地方也被引用了?这样当然只有effect会被销毁。但是我们想让ActivePloy必然随着Effect的销毁而销毁,怎么办呢?那么我们可以改改,给弱引用加上一个回调函数:

  1. class ActivePloy(object):
  2. def __init__(self, effect):
  3. self.effect = weakref.proxy(effect, self.on_effect_destroy) # 弱引用effect
  4. def active(self):
  5. """激活时,激活对应效果"""
  6. self.effect.active()
  7. def on_effect_destroy(self, effect):
  8. """
  9. effect销毁时会调用这个方法,在这里把对自己的引用都清理干净吧
  10. """
  11. pass

这样一来,就不用担心删不干净了。

转载于:https://blog.51cto.com/sleepd/1073044

Python的弱引用相关推荐

  1. python字典弱引用_python 自身遍历及弱引用的简单示例

    对python这个高级语言感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编两巴掌来看看吧! 在[python 标准库]中看到的一段代码,非常有帮助: # @param python 图 自身 ...

  2. Python 中弱引用的神奇用法与原理探析

    文章源地址:神奇的弱引用 | 小菜学编程 背景 开始讨论弱引用( weakref )之前,我们先来看看什么是弱引用?它到底有什么作用? 假设我们有一个多线程程序,并发处理应用数据: # 占用大量资源, ...

  3. python字典弱引用_如何使用弱引用优化 Python 程序的内存占用?

    Python 的垃圾回收机制通过引用计数来决定一个对象要不要被回收.当一个对象被引用次数为0时,它就会被作为垃圾回收从而释放 Python 内存.但有些情况下,我们的代码可能在不经意间导致某些实际上我 ...

  4. 弱引用的用途:在底层C++对象被上层python脚本对象使用时(转)

    在使用python脚本和底层C++对象进行交互的过程中发生了一个问题:由于底层C++对象的创建和删除决定权由底层决定,当底层决定删除这些对象而上层仍然在"强引用"这些对象的时候,就 ...

  5. python对象回收_python 引用,拷贝,对象回收,弱引用

    引用 python中,在对对象赋值,参数传递,函数返回等等, 都是引用传递的. 直接copy个例子来[1]: a = [1, 2, 3] b = a b.append(5) print a, b 输出 ...

  6. python 弱引用

    文章目录 创建弱引用 创建代理对象 循环引用 缓存对象 (WeakValueDictionary) 垃圾回收 和许多其它的高级语言一样,Python使用了垃圾回收器来自动销毁那些不再使用的对象.每个对 ...

  7. python雪峰_python雪峰python 图 自身遍历及弱引用使用

    在[python 标准库]中看到的一段代码,非常有帮助:def all_nodes(self): yield self n = self.other while n and n.name != sel ...

  8. 【python】对象释放,弱引用weaker.ref

    class A:def __del__(self):print("in__del__")>>> a = A() >>> a = None in_ ...

  9. sqlserver2008未将对象引用设置到对象的实例_面试官:ThreadLocal 的内存泄漏是弱引用导致的,你确定?...

    面试官:ThreadLocal 了解吗? Python 小星:线程局部变量,多线程下能保证各个线程的变量相对独立于其他线程的变量. 面试官:那你说下它是如何保证线程隔离的? Python 小星:每个线 ...

最新文章

  1. 用python绘制柱状图标题-使用Python绘制图表大全总结
  2. webpack为什么加载不了css?
  3. linux下删除有锁的文件夹,Linux 文件夹右下角有锁,解锁
  4. MOSS点滴(1):如何开发和部署feature
  5. 云南大学计算机网络期中考试刘春花,实验九基于CRC编码的检错程序的实现.doc...
  6. Duplicate复制数据库并创建物理StandBy(spfile+不同实例名+不同路径)
  7. [Vue.js] 路由 -- 基于vue-router的案例--后台管理
  8. 自制 python 数据分析库
  9. SQL极限函数limit()详解分页必备
  10. 优盘中发现计算机病毒怎么办,u盘中毒了文件夹被病毒隐藏怎么办?
  11. Veeam 完整备份文件 (VBK) 和增量备份文件 (VIB)
  12. 【SDOI2015】星际战争(网络流)
  13. 大学计算机专业的同学是怎么学习的?
  14. Maya2022安装教程
  15. Elastic:使用 Elastic Stack 来监督系统日志及指标
  16. 量子计算深化:大规模量子计算(相关论文108篇推荐)
  17. python如何获取星期几
  18. linux 黑屏后死机,如何修复各种各样的黑屏死机
  19. Oracle报错ORA-01507: ??????
  20. Java中xmp标签的作用_html 中 xmp标记

热门文章

  1. cmake qt 添加路径 项目_CMake配置Qt工程
  2. php-ast 开源,PHP AST学习 - osc_ryjlu6z2的个人空间 - OSCHINA - 中文开源技术交流社区...
  3. oracle 半连接 效率,关于oracle中的半连接
  4. element的滚动去掉横向_textarea去掉滚动条 textarea横向或纵向滚动条的去掉方法
  5. 标志位鼠标Java_检查标志位java
  6. java发送get post请求_【工具】java发送GET、POST请求
  7. jieba 分词的三种模式
  8. html5基础知识点表单
  9. IntelliJ IDEA如何设置添加类时注释作者信息和日期时间
  10. 关于站库分离渗透思路总结