python中的弱引用

IT *_*nja 42 python python-2.7

我一直试图理解python弱引用列表/字典的工作方式,并且也在阅读它的文档,但是我似乎无法弄清楚它们是如何工作的以及它们可以用于什么.谁能给我一个基本的例子来说明他们做了什么/解释他们是如何工作的?非常感谢.

(编辑)使用托马斯的代码,当我用[1,2,3]它代替obj 时抛出:

Traceback (most recent call last):
File "C:/Users/nonya/Desktop/test.py", line 9, in <module>
r = weakref.ref(obj)
TypeError: cannot create weak reference to 'list' object
Run Code Online (Sandbox Code Playgroud)

Tho*_*zco 54

理论

引用计数通常如下:每次创建对象的引用时,它都会增加1,每当删除引用时,它都会减1.

弱引用允许您创建对象的引用,这不会增加引用计数.

引用计数由python的垃圾收集器在运行时使用:引用计数为0的任何对象都将被垃圾收集.

您可以对昂贵的对象使用弱引用,或者避免使用循环引用(尽管垃圾收集器通常会自行执行).

用法

这是一个展示其用法的工作示例:

import weakref
import gc

class MyObject(object):
    def my_method(self):
        print 'my_method was called!'

obj = MyObject()
r = weakref.ref(obj)

gc.collect()
assert r() is obj #r() allows you to access the object referenced: it's there.

obj = 1 #Let's change what obj references to
gc.collect()
assert r() is None #There is no object left: it was gc'ed.
Run Code Online (Sandbox Code Playgroud)

  • Python的`weakref`文档建议您可以通过子类化创建对列表的弱引用:`class WeakRefableList(list):pass`.但是我不确定这会对你想做什么有所帮助,适当的范围应该足以让垃圾收集器来处理你的问题.如果需要,您可以随时使用`gc`模式来追踪内存泄漏. (4认同)
  • 它如何在列表/字典上工作,但这是关于类/函数的一个很好的例子.:) (2认同)
  • 你能看看我的编辑吗?当替换列表或字典时,它会抛出该错误。 (2认同)

jic*_*chi 27

只是想指出的是,weakref.ref不适用于内置列表工作,因为没有__weakref____slots__列表中.例如,以下代码定义了一个支持weakref的列表容器.

import weakref

class weaklist(list):
    __slots__ = '__weakref__',

l = weaklist()
r = weakref.ref(l)
Run Code Online (Sandbox Code Playgroud)

  • 哇..我多次使用`__slots__`,这给我省去了一些严重的麻烦:) (2认同)

Mar*_*cin 10

关键是它们允许将引用保留到对象,而不会阻止它们被垃圾回收.

您希望这样做的两个主要原因是您进行自己的定期资源管理,例如关闭文件,但由于这些传递之间的时间可能很长,垃圾收集器可能会为您执行此操作; 或者你在哪里创建一个对象,跟踪它在程序中的位置可能相对昂贵,但你仍然想要处理实际存在的实例.

第二种情况可能更常见 - 当您持有例如要通知的对象列表时,它是合适的,并且您不希望通知系统阻止垃圾收集.

  • @dashesy 说得对。弱引用最常见(_可以说是唯一安全_)的用例是显式中断引用循环。尽管Python垃圾收集器无论如何都可以并且最终会打破这样的循环,但是从一开始就防止这样的循环形成所需的空间和时间要少得多。弱引用的所有其他用途充其量都是脆弱的,绝对应该以一点恐惧和尊重的态度对待。 (2认同)