问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

python 什么时候使用 weakref

发布网友 发布时间:2022-04-24 09:51

我来回答

2个回答

懂视网 时间:2022-05-11 01:48

在【python 标准库】中看到的一段代码,非常有帮助:

def all_nodes(self):
 yield self
 n = self.other
 while n and n.name != self.name:
  yield n
  n = n.other
 if n is self:
  yield n
 return


首尾的2处yield均只返回一次,作为循环图的起点、终点,而n作为图可能的节点,每次在next调用中均返回next节点

利用这个迭代器,就可以轻松打印出图的结构:

def __str__(self):

return '->'.join((n.name for n in self.all_nodes()))


Graph:

one->two->three->one


实现一个图结构需要利用python里面的弱引用,

我们先看一下标准的向图结构中增加下一节点的代码:

def set_next(self, other):

print '%s.next %r' % ( self.name, other)

self.other = other


这样绑定后,在属性字段中,增加一个对于下一节点的引用

c.__dict__

{'other': , 'name': '1'}


所以,即使手动调用了 a = None, b = None, c = None,对象也不会被删除

Garbage:[,

,

,

{'name': 'one', 'other': },

{'name': 'two', 'other': },

{'name': 'three', 'other': }]

而弱引用是指“引用一个对象,但并不增加被引用对象的指针计数”

可以通过c = weekref.ref(k,func)

来指定引用的对象及对象删除后的动作func

调用时,使用c() 来引用k

但是在上个例子里面,我们需要一个“代理对象”来代理这个被引用的对象,从而使set_next 函数对于变量other可以同正常变量一样使用

def set_next(self, other):
 if other is not None:
  if self in other.all_nodes():
  other = weakref.proxy(other)
 super(WeakGraph, self).set_next(other)
 return


从而避免了通过other()来引用一个other对象~

热心网友 时间:2022-05-10 22:56

  和许多其它的高级语言一样,Python使用了垃圾回收器来自动销毁那些不再使用的对象。每个对象都有一个引用计数,当这个引用计数为0时Python能够安全地销毁这个对象。
  使用weakref模块,你可以创建到对象的弱引用,Python在对象的引用计数为0或只存在对象的弱引用时将回收这个对象。
  一、 创建弱引用
  你可以通过调用weakref模块的ref(obj[,callback])来创建一个弱引用,obj是你想弱引用的对象,callback是一个可选的函数,当因没有引用导致Python要销毁这个对象时调用。回调函数callback要求单个参数(弱引用的对象)。
  一旦你有了一个对象的弱引用,你就能通过调用弱引用来获取被弱引用的对象。下面的例子创建了一个对socket对象的弱引用:
  >>> from socket import *
  >>> import weakref
  >>> s=socket(AF_INET,SOCK_STREAM)
  >>> ref=weakref.ref(s)
  >>> s
  <socket._socketobject instance at 007B4A94>
  >>> ref
  <weakref at 0x81195c; to 'instance' at 0x7b4a94>
  >>> ref() #调用它来访问被引用的对象
  <socket.socketobject instance at 007B4A94>
  一旦没有了对这个对象的其它的引用,调用弱引用将返回None,因为Python已经销毁了这个对象。 注意:大部分的对象不能通过弱引用来访问。
  weakref模块中的getweakrefcount(obj)和getweakrefs(obj)分别返回弱引用数和关于所给对象的引用列表。
  弱引用对于创建对象(这些对象很费资源)的缓存是有用的。
  二、创建代理对象
  代理对象是弱引用对象,它们的行为就像它们所引用的对象,这就便于你不必首先调用弱引用来访问背后的对象。通过weakref模块的proxy(obj[,callback])函数来创建代理对象。使用代理对象就如同使用对象本身一样:
  >>> from socket import*
  >>> import weakref
  >>> s=socket(AF_INET,SOCK_STREAM)
  >>> ref=weakref.proxy(s)
  >>> s
  <socket._socketobject instance at 007E4874>
  >>> ref
  <socket._socketobject instance at 007E4874>
  >>> ref.close() #对象的方法同样工作
  callback参数的目的和ref函数相同。在Python删除了一个引用的对象之后,使用代理将会导致一个weakref.ReferenceError错误:
  >>> def s
  >>> ref
  Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  弱引用使用的机会不是很多,一般用来进行 cache 编程。我们可以使用 weakref.ref() 来创建一个弱引用。
  >>>> import sys
  >>> import weakref
  >>> class Class1:
  def test(self):
  print "test..."
  >>> o = Class1()
  >>> sys.getrefcount(o)
  2
  >>> r = weakref.ref(o) # 创建一个弱引用
  >>> sys.getrefcount(o) # 引用计数并没有改变
  2
  >>> r
  <weakref at 00D3B3F0; to 'instance' at 00D37A30> # 弱引用所指向的对象信息
  >>> o2 = r() # 获取弱引用所指向的对象
  >>> o is o2
  True
  >>> sys.getrefcount(o)
  3
  >>> o = None
  >>> o2 = None
  >>> r # 当对象引用计数为零时,弱引用失效。
  <weakref at 00D3B3F0; dead>de>
  weakref 还提供了一个 proxy():
  import sys
  import weakref
  class Class1:
  def test(self):
  print "test"
  def callback(self):
  print "callback"
  o = Class1()
  p = weakref.proxy(o, callback)
  p.test()
  o = None
  python的弱引用指引用一个对象但不增加它的引用计数器。这么做的好处是什么呢?什么时候需要考虑用若引用呢?
  假设我们在设计一个游戏,有一个角色类Char,我们要给他添加一个效果(比如中毒),于是设计了一个效果类Effect。现在,给角色增加效果看上去就像这样:
  char.effect=Effect()# 给角色添加一个效果
  每个效果生效的时机都是不同的,为了方便复用,我们再设计一个激活策略类ActivePloy,负责激活效果。于是在Effect和ActivePloy的内部看上去就像这样:
  classEffect(object):
  def__init__(self):
  self.active_ploy=ActivePloy(self)
  defactive(self):
  """激活时的处理"""
  pass
  classActivePloy(object):
  def__init__(self,effect):
  self.effect=effect
  defactive(self):
  """激活时,激活对应效果"""
  self.effect.active()
  这样做的好处是Effect不用关心自己何时激活,激活的判断都放给ActivePloy来处理。看上去挺好的,但是,这里面有一个问题,就是当我们试图给玩家去掉这个效果时……
  delchar.effect
  仔细想想,这么干以后,Effect的实例其实是没有被回收的,因为Effect和ActivePloy交叉引用,他们的引用计数都为1。
  那么我们为了干净的删除effect,似乎就只能手动的来清理一下他们之间的这个交叉引用了:
  classEffect(object):
  def__init__(self):
  self.active_ploy=ActivePloy(self)
  defactive(self):
  """激活时的处理"""
  pass
  defdestroy(self):
  self.active_ploy.destroy()
  classActivePloy(object):
  def__init__(self,effect):
  self.effect=effect
  defactive(self):
  """激活时,激活对应效果"""
  self.effect.active()
  defdestroy(self):
  self.effect=None
  于是我们要删除一个效果,就得这样:
  char.effect.destroy()
  delchar.effect
  太麻烦了,不是吗?而且万一一个效果有多个激活策略的话,必须保证Effect把每个ActivePloy的destroy方法都运行一遍,漏了一个都无法保证自身被干净的删除。
  我们来分析一下,之所以这么麻烦,就是因为ActivePloy对Effect有一个引用。那么如果ActivePloy不引用Effect不就OK了?这个时候,让我们来试试弱引用。
  importweakref
  classEffect(object):
  def__init__(self):
  self.active_ploy=ActivePloy(self)
  defactive(self):
  """激活时的处理"""
  pass
  classActivePloy(object):
  def__init__(self,effect):
  self.effect=weakref.proxy(effect)#弱引用effect
  defactive(self):
  """激活时,激活对应效果"""
  self.effect.active()
  代码只有一个地方改变了,就是
  self.effect=weakref.proxy(effect)
  这句的效果就是self.effect可以像往常一样的使用,但是却不会增加effect的引用计数器。换言之,这样写,他们之间的交叉关系消失了!这个时候我们只需要单纯的删掉char.effect,Effect和ActivePloy的实例都会被销毁。
  什么,假设ActivePloy在其他地方也被引用了?这样当然只有effect会被销毁。但是我们想让ActivePloy必然随着Effect的销毁而销毁,怎么办呢?那么我们可以改改,给弱引用加上一个回调函数:
  classActivePloy(object):
  def__init__(self,effect):
  self.effect=weakref.proxy(effect,self.on_effect_destroy)#弱引用effect
  defactive(self):
  """激活时,激活对应效果"""
  self.effect.active()
  defon_effect_destroy(self,effect):
  """
  effect销毁时会调用这个方法,在这里把对自己的引用都清理干净吧
  """
  pass
  这样一来,就不用担心删不干净了。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
在线坐等,西游记片头曲叫什么名字?,劳驾你们 ...想要《西游记》孙悟空大闹天宫时的那个歌曲?,劳驾喽 亲们给个,西游记片头曲叫什么名字?,劳驾大家 希望有亲告诉,西游记片头曲叫什么名字?,劳驾亲们 基金日涨幅0.00%是什么意思? 大盘涨了可是基金增长为0,是什么情况 柯南铃木特快车是哪一集 右腹部靠近腰一阵一阵疼,绞痛不是很剧烈但是频繁_百度拇指医生 铃木特快列车是哪一集 股票美人肩是什么意思 关于前端转 Node 不知道大家有什么看法 在python中出现这种情况为什么 小天才电话手表z2y主板坏了,能修吗? 小天才手表怎么卸电池 scrapy 在pycharm 中为什么没有代码提示? Python里的(array:list)-&gt;int 啥意思? python是动态类型的?到底算是强类型的还是弱类型的呢 怎样才能学好弱类型语言,比如Python Python是不是弱类型?如果是的话是不是仅仅因此就不需要泛型了? Python是不是弱类型?如果是的话是不是仅仅因此就不需要泛型了_百度知 ... python是动态语言,是不是弱类型语言 怎么总有人说python是弱类型语言 华为收购新亚制程多少股份 可以把华为账号中的游戏数据转移到另一个华为账号吗? 在不开机的情况下,怎样给手机电池放电,手机不能开机!麻烦了? 华为向国开行转让应收账款 相关部门提示风险 华为的资本债务结构会发生如何变化? 任正非有意出售5G核心技术,卖给哪个公司的可能性最大? 荣耀被卖给谁了 华为荣耀卖给谁了? 华为 股权 如何变现 Python有什么缺点呢? 小天才手表拆卸电池可以消除密码吗 小天才电话手表Z2不能充进电怎么办? 描绘爱情的诗词 手机电池如何人工放电 梦见自己跟别人在救火,火打不息? 老是梦见着火了救火←但没有全灭了我总觉的会有不好的事要发生请专业... 梦见自己去加油,可是油站冒出好多浓烟感觉爆炸的样子,我就把车丢了跑出去,一会就爆炸了 梦见加油站是什么意思? 梦见自己把加油站点燃还冒烟有点火苗 多字猜一生肖 很多人说颗粒板是最差的板材,这到底是为什么呢? (多)字解十二生肖中何肖 美的TA102和TA100空调那款好? 家具是实木的好还是实木颗粒板的好?求专业的咨询? 多字解那一生肖 美的壁挂式空调TA101(B1)与XT100(1)哪个好? 实木家具一直都有味道,不知是甲醛味还是木头的味道,一直敞了3年了,还是不散。 十二生肖,多是指哪个生肖 美的空调舒适星TA100跟TA102区别